2006-07-16 01:46:36 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
|
|
|
|
* This file is part of SIGAR.
|
|
|
|
*
|
|
|
|
* SIGAR is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms version 2 of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation. This program is distributed
|
|
|
|
* in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
|
|
|
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
|
|
* PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
|
|
* USA.
|
|
|
|
*/
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include "sigar.h"
|
|
|
|
#include "sigar_private.h"
|
|
|
|
#include "sigar_util.h"
|
2004-12-06 05:09:47 +08:00
|
|
|
#include "sigar_os.h"
|
2004-06-22 06:37:04 +08:00
|
|
|
|
|
|
|
SIGAR_DECLARE(int) sigar_open(sigar_t **sigar)
|
|
|
|
{
|
|
|
|
int status = sigar_os_open(sigar);
|
|
|
|
|
|
|
|
if (status == SIGAR_OK) {
|
|
|
|
(*sigar)->pid = 0;
|
|
|
|
(*sigar)->ifconf_buf = NULL;
|
|
|
|
(*sigar)->ifconf_len = 0;
|
|
|
|
(*sigar)->log_level = -1; /* log nothing by default */
|
|
|
|
(*sigar)->log_impl = NULL;
|
|
|
|
(*sigar)->log_data = NULL;
|
2007-03-12 05:46:41 +08:00
|
|
|
(*sigar)->ptql_re_impl = NULL;
|
|
|
|
(*sigar)->ptql_re_data = NULL;
|
2005-12-15 02:35:19 +08:00
|
|
|
(*sigar)->self_path = NULL;
|
2007-03-12 05:46:41 +08:00
|
|
|
(*sigar)->proc_cpu = NULL;
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_DECLARE(int) sigar_close(sigar_t *sigar)
|
|
|
|
{
|
|
|
|
if (sigar->ifconf_buf) {
|
|
|
|
free(sigar->ifconf_buf);
|
|
|
|
}
|
2005-12-15 02:35:19 +08:00
|
|
|
if (sigar->self_path) {
|
|
|
|
free(sigar->self_path);
|
|
|
|
}
|
2007-03-12 05:46:41 +08:00
|
|
|
if (sigar->proc_cpu) {
|
|
|
|
sigar_cache_destroy(sigar->proc_cpu);
|
|
|
|
}
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
return sigar_os_close(sigar);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef __linux__ /* linux has a special case */
|
|
|
|
SIGAR_DECLARE(sigar_pid_t) sigar_pid_get(sigar_t *sigar)
|
|
|
|
{
|
|
|
|
if (!sigar->pid) {
|
|
|
|
sigar->pid = getpid();
|
|
|
|
}
|
|
|
|
|
|
|
|
return sigar->pid;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-03-12 05:46:41 +08:00
|
|
|
/* XXX: add clear() function */
|
|
|
|
/* XXX: check for stale-ness using start_time */
|
|
|
|
SIGAR_DECLARE(int) sigar_proc_cpu_get(sigar_t *sigar, sigar_pid_t pid,
|
|
|
|
sigar_proc_cpu_t *proccpu)
|
|
|
|
{
|
|
|
|
sigar_cache_entry_t *entry;
|
|
|
|
sigar_proc_cpu_t *prev;
|
|
|
|
sigar_uint64_t otime, time_now = time(NULL) * 1000;
|
|
|
|
sigar_int64_t time_diff, total_diff;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
if (!sigar->proc_cpu) {
|
|
|
|
sigar->proc_cpu = sigar_cache_new(128);
|
|
|
|
}
|
|
|
|
|
|
|
|
entry = sigar_cache_get(sigar->proc_cpu, pid);
|
|
|
|
if (entry->value) {
|
|
|
|
prev = (sigar_proc_cpu_t *)entry->value;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
prev = entry->value = malloc(sizeof(*prev));
|
|
|
|
SIGAR_ZERO(prev);
|
|
|
|
}
|
|
|
|
|
|
|
|
time_diff = time_now - prev->last_time;
|
|
|
|
proccpu->last_time = prev->last_time = time_now;
|
|
|
|
|
|
|
|
if (time_diff == 0) {
|
|
|
|
/* we were just called within < 1 second ago. */
|
|
|
|
memcpy(proccpu, prev, sizeof(*proccpu));
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
otime = prev->total;
|
|
|
|
|
|
|
|
status =
|
|
|
|
sigar_proc_time_get(sigar, pid,
|
|
|
|
(sigar_proc_time_t *)proccpu);
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(prev, proccpu, sizeof(*prev));
|
|
|
|
|
|
|
|
if (otime == 0) {
|
|
|
|
/* first time called */
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
total_diff = proccpu->total - otime;
|
|
|
|
proccpu->percent = total_diff / (double)time_diff;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
static char *sigar_error_string(int err)
|
|
|
|
{
|
|
|
|
switch (err) {
|
|
|
|
case SIGAR_ENOTIMPL:
|
|
|
|
return "This function has not been implemented on this platform";
|
|
|
|
default:
|
|
|
|
return "Error string not specified yet";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_DECLARE(char *) sigar_strerror(sigar_t *sigar, int err)
|
|
|
|
{
|
2007-01-04 06:47:00 +08:00
|
|
|
char *buf;
|
2004-06-22 06:37:04 +08:00
|
|
|
|
|
|
|
if (err > SIGAR_OS_START_ERROR) {
|
2005-03-12 14:19:34 +08:00
|
|
|
if ((buf = sigar_os_error_string(sigar, err)) != NULL) {
|
2004-06-22 06:37:04 +08:00
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
return "Unknown OS Error"; /* should never happen */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (err > SIGAR_START_ERROR) {
|
|
|
|
return sigar_error_string(err);
|
|
|
|
}
|
|
|
|
|
2007-01-04 06:47:00 +08:00
|
|
|
return sigar_strerror_get(err, sigar->errbuf, sizeof(sigar->errbuf));
|
|
|
|
}
|
|
|
|
|
|
|
|
char *sigar_strerror_get(int err, char *errbuf, int buflen)
|
|
|
|
{
|
|
|
|
char *buf = NULL;
|
2004-06-22 06:37:04 +08:00
|
|
|
#ifdef WIN32
|
2007-01-04 06:47:00 +08:00
|
|
|
DWORD len;
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
|
|
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
|
|
NULL,
|
|
|
|
err,
|
|
|
|
0, /* default language */
|
2007-01-04 06:47:00 +08:00
|
|
|
(LPTSTR)errbuf,
|
|
|
|
(DWORD)buflen,
|
2004-06-22 06:37:04 +08:00
|
|
|
NULL);
|
|
|
|
#else
|
|
|
|
|
|
|
|
#if defined(HAVE_STRERROR_R) && defined(HAVE_STRERROR_R_GLIBC)
|
|
|
|
/*
|
|
|
|
* strerror_r man page says:
|
|
|
|
* "The GNU version may, but need not, use the user supplied buffer"
|
|
|
|
*/
|
2007-01-04 06:47:00 +08:00
|
|
|
buf = strerror_r(err, errbuf, buflen);
|
2004-06-22 06:37:04 +08:00
|
|
|
#elif defined(HAVE_STRERROR_R)
|
2007-01-04 06:47:00 +08:00
|
|
|
if (strerror_r(err, errbuf, buflen) < 0) {
|
2004-06-22 06:37:04 +08:00
|
|
|
buf = "Unknown Error";
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
/* strerror() is thread safe on solaris and hpux */
|
|
|
|
buf = strerror(err);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (buf != NULL) {
|
2007-01-04 06:47:00 +08:00
|
|
|
SIGAR_STRNCPY(errbuf, buf, buflen);
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
2007-01-04 06:47:00 +08:00
|
|
|
return errbuf;
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#include <stdio.h> /* for sprintf */
|
|
|
|
|
|
|
|
SIGAR_DECLARE(int) sigar_uptime_string(sigar_t *sigar,
|
|
|
|
sigar_uptime_t *uptime,
|
|
|
|
char *buffer,
|
|
|
|
int buflen)
|
|
|
|
{
|
|
|
|
char *ptr = buffer;
|
|
|
|
int minutes, hours, days, offset = 0;
|
|
|
|
|
|
|
|
/* XXX: get rid of sprintf and/or check for overflow */
|
|
|
|
days = uptime->uptime / (60*60*24);
|
|
|
|
|
|
|
|
if (days) {
|
|
|
|
offset += sprintf(ptr + offset, "%d day%s, ",
|
|
|
|
days, (days > 1) ? "s" : "");
|
|
|
|
}
|
|
|
|
|
|
|
|
minutes = (int)uptime->uptime / 60;
|
|
|
|
hours = minutes / 60;
|
|
|
|
hours = hours % 24;
|
|
|
|
minutes = minutes % 60;
|
|
|
|
|
|
|
|
if (hours) {
|
|
|
|
offset += sprintf(ptr + offset, "%2d:%02d",
|
|
|
|
hours, minutes);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
offset += sprintf(ptr + offset, "%d min", minutes);
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy apr_strfsize */
|
|
|
|
SIGAR_DECLARE(char *) sigar_format_size(sigar_uint64_t size, char *buf)
|
|
|
|
{
|
|
|
|
const char ord[] = "KMGTPE";
|
|
|
|
const char *o = ord;
|
|
|
|
int remain;
|
|
|
|
|
2005-02-19 10:06:02 +08:00
|
|
|
if (size == SIGAR_FIELD_NOTIMPL) {
|
|
|
|
buf[0] = '-';
|
|
|
|
buf[1] = '\0';
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
if (size < 973) {
|
|
|
|
sprintf(buf, "%3d ", (int) size);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
remain = (int)(size & 1023);
|
|
|
|
size >>= 10;
|
|
|
|
|
|
|
|
if (size >= 973) {
|
|
|
|
++o;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (size < 9 || (size == 9 && remain < 973)) {
|
|
|
|
if ((remain = ((remain * 5) + 256) / 512) >= 10) {
|
|
|
|
++size;
|
|
|
|
remain = 0;
|
|
|
|
}
|
|
|
|
sprintf(buf, "%d.%d%c", (int) size, remain, *o);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (remain >= 512) {
|
|
|
|
++size;
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf(buf, "%3d%c", (int) size, *o);
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
} while (1);
|
|
|
|
}
|
|
|
|
|
2006-09-25 08:08:50 +08:00
|
|
|
SIGAR_DECLARE(int) sigar_sys_info_get(sigar_t *sigar,
|
|
|
|
sigar_sys_info_t *sysinfo)
|
|
|
|
{
|
|
|
|
SIGAR_ZERO(sysinfo);
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
#ifndef WIN32
|
2006-09-25 08:08:50 +08:00
|
|
|
sigar_sys_info_get_uname(sysinfo);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
sigar_os_sys_info_get(sigar, sysinfo);
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
|
|
|
|
int sigar_sys_info_get_uname(sigar_sys_info_t *sysinfo)
|
|
|
|
{
|
|
|
|
struct utsname name;
|
|
|
|
|
|
|
|
uname(&name);
|
|
|
|
|
|
|
|
SIGAR_SSTRCPY(sysinfo->version, name.release);
|
|
|
|
SIGAR_SSTRCPY(sysinfo->vendor_name, name.sysname);
|
|
|
|
SIGAR_SSTRCPY(sysinfo->name, name.sysname);
|
2006-09-25 09:47:33 +08:00
|
|
|
SIGAR_SSTRCPY(sysinfo->machine, name.machine);
|
2006-09-25 08:08:50 +08:00
|
|
|
SIGAR_SSTRCPY(sysinfo->arch, name.machine);
|
|
|
|
SIGAR_SSTRCPY(sysinfo->patch_level, "unknown");
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
#include <pwd.h>
|
|
|
|
#include <grp.h>
|
|
|
|
|
|
|
|
int sigar_user_name_get(sigar_t *sigar, int uid, char *buf, int buflen)
|
|
|
|
{
|
2005-10-02 11:07:59 +08:00
|
|
|
struct passwd *pw = NULL;
|
2004-06-22 06:37:04 +08:00
|
|
|
/* XXX cache lookup */
|
|
|
|
|
|
|
|
# ifdef HAVE_GETPWUID_R
|
|
|
|
struct passwd pwbuf;
|
|
|
|
char buffer[512];
|
|
|
|
|
|
|
|
if (getpwuid_r(uid, &pwbuf, buffer, sizeof(buffer), &pw) != 0) {
|
|
|
|
return errno;
|
|
|
|
}
|
2005-10-02 11:07:59 +08:00
|
|
|
if (!pw) {
|
|
|
|
return ENOENT;
|
|
|
|
}
|
2004-06-22 06:37:04 +08:00
|
|
|
# else
|
|
|
|
if ((pw = getpwuid(uid)) == NULL) {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
|
|
|
|
strncpy(buf, pw->pw_name, buflen);
|
|
|
|
buf[buflen-1] = '\0';
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_group_name_get(sigar_t *sigar, int gid, char *buf, int buflen)
|
|
|
|
{
|
|
|
|
struct group *gr;
|
|
|
|
/* XXX cache lookup */
|
|
|
|
|
|
|
|
# ifdef HAVE_GETGRGID_R
|
|
|
|
struct group grbuf;
|
|
|
|
char buffer[512];
|
|
|
|
|
|
|
|
if (getgrgid_r(gid, &grbuf, buffer, sizeof(buffer), &gr) != 0) {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
# else
|
|
|
|
if ((gr = getgrgid(gid)) == NULL) {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
|
2004-11-30 08:14:06 +08:00
|
|
|
if (gr && gr->gr_name) {
|
|
|
|
strncpy(buf, gr->gr_name, buflen);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* seen on linux.. apache httpd.conf has:
|
|
|
|
* Group #-1
|
|
|
|
* results in uid == -1 and gr == NULL.
|
|
|
|
* wtf getgrgid_r doesnt fail instead?
|
|
|
|
*/
|
|
|
|
sprintf(buf, "%d", gid);
|
|
|
|
}
|
2004-06-22 06:37:04 +08:00
|
|
|
buf[buflen-1] = '\0';
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_user_id_get(sigar_t *sigar, const char *name, int *uid)
|
|
|
|
{
|
|
|
|
/* XXX cache lookup */
|
|
|
|
struct passwd *pw;
|
|
|
|
|
|
|
|
# ifdef HAVE_GETPWNAM_R
|
|
|
|
struct passwd pwbuf;
|
|
|
|
char buf[512];
|
|
|
|
|
|
|
|
if (getpwnam_r(name, &pwbuf, buf, sizeof(buf), &pw) != 0) {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
# else
|
|
|
|
if (!(pw = getpwnam(name))) {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
|
|
|
|
*uid = (int)pw->pw_uid;
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_DECLARE(int)
|
|
|
|
sigar_proc_cred_name_get(sigar_t *sigar, sigar_pid_t pid,
|
|
|
|
sigar_proc_cred_name_t *proccredname)
|
|
|
|
{
|
|
|
|
sigar_proc_cred_t cred;
|
|
|
|
|
|
|
|
int status = sigar_proc_cred_get(sigar, pid, &cred);
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
status = sigar_user_name_get(sigar, cred.uid,
|
|
|
|
proccredname->user,
|
|
|
|
sizeof(proccredname->user));
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
status = sigar_group_name_get(sigar, cred.gid,
|
|
|
|
proccredname->group,
|
|
|
|
sizeof(proccredname->group));
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* WIN32 */
|
|
|
|
|
|
|
|
int sigar_proc_list_create(sigar_proc_list_t *proclist)
|
|
|
|
{
|
|
|
|
proclist->number = 0;
|
|
|
|
proclist->size = SIGAR_PROC_LIST_MAX;
|
|
|
|
proclist->data = malloc(sizeof(*(proclist->data)) *
|
|
|
|
proclist->size);
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_proc_list_grow(sigar_proc_list_t *proclist)
|
|
|
|
{
|
|
|
|
proclist->data = realloc(proclist->data,
|
|
|
|
sizeof(*(proclist->data)) *
|
|
|
|
(proclist->size + SIGAR_PROC_LIST_MAX));
|
|
|
|
proclist->size += SIGAR_PROC_LIST_MAX;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_DECLARE(int) sigar_proc_list_destroy(sigar_t *sigar,
|
|
|
|
sigar_proc_list_t *proclist)
|
|
|
|
{
|
|
|
|
if (proclist->size) {
|
|
|
|
free(proclist->data);
|
|
|
|
proclist->number = proclist->size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_proc_args_create(sigar_proc_args_t *procargs)
|
|
|
|
{
|
|
|
|
procargs->number = 0;
|
|
|
|
procargs->size = SIGAR_PROC_ARGS_MAX;
|
|
|
|
procargs->data = malloc(sizeof(*(procargs->data)) *
|
|
|
|
procargs->size);
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_proc_args_grow(sigar_proc_args_t *procargs)
|
|
|
|
{
|
|
|
|
procargs->data = realloc(procargs->data,
|
|
|
|
sizeof(*(procargs->data)) *
|
|
|
|
(procargs->size + SIGAR_PROC_ARGS_MAX));
|
|
|
|
procargs->size += SIGAR_PROC_ARGS_MAX;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_DECLARE(int) sigar_proc_args_destroy(sigar_t *sigar,
|
|
|
|
sigar_proc_args_t *procargs)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if (procargs->size) {
|
|
|
|
for (i=0; i<procargs->number; i++) {
|
|
|
|
free(procargs->data[i]);
|
|
|
|
}
|
|
|
|
free(procargs->data);
|
|
|
|
procargs->number = procargs->size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_file_system_list_create(sigar_file_system_list_t *fslist)
|
|
|
|
{
|
|
|
|
fslist->number = 0;
|
|
|
|
fslist->size = SIGAR_FS_MAX;
|
|
|
|
fslist->data = malloc(sizeof(*(fslist->data)) *
|
|
|
|
fslist->size);
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_file_system_list_grow(sigar_file_system_list_t *fslist)
|
|
|
|
{
|
|
|
|
fslist->data = realloc(fslist->data,
|
|
|
|
sizeof(*(fslist->data)) *
|
|
|
|
(fslist->size + SIGAR_FS_MAX));
|
|
|
|
fslist->size += SIGAR_FS_MAX;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* indexed with sigar_file_system_type_e */
|
|
|
|
static const char *fstype_names[] = {
|
|
|
|
"unknown", "none", "local", "remote", "ram", "cdrom", "swap"
|
|
|
|
};
|
|
|
|
|
|
|
|
static int sigar_common_fs_type_get(sigar_file_system_t *fsp)
|
|
|
|
{
|
|
|
|
char *type = fsp->sys_type_name;
|
|
|
|
|
|
|
|
switch (*type) {
|
|
|
|
case 'n':
|
|
|
|
if (strEQ(type, "nfs")) {
|
|
|
|
fsp->type = SIGAR_FSTYPE_NETWORK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
if (strEQ(type, "smbfs")) { /* samba */
|
|
|
|
fsp->type = SIGAR_FSTYPE_NETWORK;
|
|
|
|
}
|
|
|
|
else if (strEQ(type, "swap")) {
|
|
|
|
fsp->type = SIGAR_FSTYPE_SWAP;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
if (strEQ(type, "afs")) {
|
|
|
|
fsp->type = SIGAR_FSTYPE_NETWORK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
if (strEQ(type, "iso9660")) {
|
|
|
|
fsp->type = SIGAR_FSTYPE_CDROM;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
if (strEQ(type, "msdos") || strEQ(type, "minix")) {
|
|
|
|
fsp->type = SIGAR_FSTYPE_LOCAL_DISK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
if (strEQ(type, "hpfs")) {
|
|
|
|
fsp->type = SIGAR_FSTYPE_LOCAL_DISK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
if (strEQ(type, "vfat")) {
|
|
|
|
fsp->type = SIGAR_FSTYPE_LOCAL_DISK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fsp->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
void sigar_fs_type_get(sigar_file_system_t *fsp)
|
|
|
|
{
|
|
|
|
if (!(fsp->type || /* already set */
|
|
|
|
sigar_os_fs_type_get(fsp) || /* try os specifics first */
|
|
|
|
sigar_common_fs_type_get(fsp))) /* try common ones last */
|
|
|
|
{
|
|
|
|
fsp->type = SIGAR_FSTYPE_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fsp->type >= SIGAR_FSTYPE_MAX) {
|
|
|
|
fsp->type = SIGAR_FSTYPE_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(fsp->type_name, fstype_names[fsp->type]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SIGAR_DECLARE(int)
|
|
|
|
sigar_file_system_list_destroy(sigar_t *sigar,
|
|
|
|
sigar_file_system_list_t *fslist)
|
|
|
|
{
|
|
|
|
if (fslist->size) {
|
|
|
|
free(fslist->data);
|
|
|
|
fslist->number = fslist->size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
2004-07-10 12:44:45 +08:00
|
|
|
int sigar_cpu_info_list_create(sigar_cpu_info_list_t *cpu_infos)
|
2004-06-22 06:37:04 +08:00
|
|
|
{
|
|
|
|
cpu_infos->number = 0;
|
|
|
|
cpu_infos->size = SIGAR_CPU_INFO_MAX;
|
|
|
|
cpu_infos->data = malloc(sizeof(*(cpu_infos->data)) *
|
|
|
|
cpu_infos->size);
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
2004-07-10 12:44:45 +08:00
|
|
|
int sigar_cpu_info_list_grow(sigar_cpu_info_list_t *cpu_infos)
|
2004-06-22 06:37:04 +08:00
|
|
|
{
|
|
|
|
cpu_infos->data = realloc(cpu_infos->data,
|
|
|
|
sizeof(*(cpu_infos->data)) *
|
|
|
|
(cpu_infos->size + SIGAR_CPU_INFO_MAX));
|
|
|
|
cpu_infos->size += SIGAR_CPU_INFO_MAX;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
2004-07-10 12:44:45 +08:00
|
|
|
SIGAR_DECLARE(int)
|
|
|
|
sigar_cpu_info_list_destroy(sigar_t *sigar,
|
|
|
|
sigar_cpu_info_list_t *cpu_infos)
|
2004-06-22 06:37:04 +08:00
|
|
|
{
|
|
|
|
if (cpu_infos->size) {
|
|
|
|
free(cpu_infos->data);
|
|
|
|
cpu_infos->number = cpu_infos->size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_cpu_list_create(sigar_cpu_list_t *cpulist)
|
|
|
|
{
|
|
|
|
cpulist->number = 0;
|
|
|
|
cpulist->size = SIGAR_CPU_INFO_MAX;
|
|
|
|
cpulist->data = malloc(sizeof(*(cpulist->data)) *
|
|
|
|
cpulist->size);
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_cpu_list_grow(sigar_cpu_list_t *cpulist)
|
|
|
|
{
|
|
|
|
cpulist->data = realloc(cpulist->data,
|
|
|
|
sizeof(*(cpulist->data)) *
|
|
|
|
(cpulist->size + SIGAR_CPU_INFO_MAX));
|
|
|
|
cpulist->size += SIGAR_CPU_INFO_MAX;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_DECLARE(int) sigar_cpu_list_destroy(sigar_t *sigar,
|
|
|
|
sigar_cpu_list_t *cpulist)
|
|
|
|
{
|
|
|
|
if (cpulist->size) {
|
|
|
|
free(cpulist->data);
|
|
|
|
cpulist->number = cpulist->size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_net_route_list_create(sigar_net_route_list_t *routelist)
|
|
|
|
{
|
|
|
|
routelist->number = 0;
|
|
|
|
routelist->size = SIGAR_NET_ROUTE_LIST_MAX;
|
|
|
|
routelist->data = malloc(sizeof(*(routelist->data)) *
|
|
|
|
routelist->size);
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_net_route_list_grow(sigar_net_route_list_t *routelist)
|
|
|
|
{
|
|
|
|
routelist->data =
|
|
|
|
realloc(routelist->data,
|
|
|
|
sizeof(*(routelist->data)) *
|
|
|
|
(routelist->size + SIGAR_NET_ROUTE_LIST_MAX));
|
|
|
|
routelist->size += SIGAR_NET_ROUTE_LIST_MAX;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_DECLARE(int) sigar_net_route_list_destroy(sigar_t *sigar,
|
|
|
|
sigar_net_route_list_t *routelist)
|
|
|
|
{
|
|
|
|
if (routelist->size) {
|
|
|
|
free(routelist->data);
|
|
|
|
routelist->number = routelist->size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_net_interface_list_create(sigar_net_interface_list_t *iflist)
|
|
|
|
{
|
|
|
|
iflist->number = 0;
|
|
|
|
iflist->size = SIGAR_NET_IFLIST_MAX;
|
|
|
|
iflist->data = malloc(sizeof(*(iflist->data)) *
|
|
|
|
iflist->size);
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_net_interface_list_grow(sigar_net_interface_list_t *iflist)
|
|
|
|
{
|
|
|
|
iflist->data = realloc(iflist->data,
|
|
|
|
sizeof(*(iflist->data)) *
|
|
|
|
(iflist->size + SIGAR_NET_IFLIST_MAX));
|
|
|
|
iflist->size += SIGAR_NET_IFLIST_MAX;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_DECLARE(int)
|
|
|
|
sigar_net_interface_list_destroy(sigar_t *sigar,
|
|
|
|
sigar_net_interface_list_t *iflist)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if (iflist->size) {
|
|
|
|
for (i=0; i<iflist->number; i++) {
|
|
|
|
free(iflist->data[i]);
|
|
|
|
}
|
|
|
|
free(iflist->data);
|
|
|
|
iflist->number = iflist->size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_net_connection_list_create(sigar_net_connection_list_t *connlist)
|
|
|
|
{
|
|
|
|
connlist->number = 0;
|
|
|
|
connlist->size = SIGAR_NET_CONNLIST_MAX;
|
|
|
|
connlist->data = malloc(sizeof(*(connlist->data)) *
|
|
|
|
connlist->size);
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_net_connection_list_grow(sigar_net_connection_list_t *connlist)
|
|
|
|
{
|
|
|
|
connlist->data =
|
|
|
|
realloc(connlist->data,
|
|
|
|
sizeof(*(connlist->data)) *
|
|
|
|
(connlist->size + SIGAR_NET_CONNLIST_MAX));
|
|
|
|
connlist->size += SIGAR_NET_CONNLIST_MAX;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_DECLARE(int)
|
|
|
|
sigar_net_connection_list_destroy(sigar_t *sigar,
|
|
|
|
sigar_net_connection_list_t *connlist)
|
|
|
|
{
|
|
|
|
if (connlist->size) {
|
|
|
|
free(connlist->data);
|
|
|
|
connlist->number = connlist->size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_DECLARE(const char *)sigar_net_connection_type_get(int type)
|
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case SIGAR_NETCONN_TCP:
|
|
|
|
return "tcp";
|
|
|
|
case SIGAR_NETCONN_UDP:
|
|
|
|
return "udp";
|
|
|
|
case SIGAR_NETCONN_RAW:
|
|
|
|
return "raw";
|
|
|
|
case SIGAR_NETCONN_UNIX:
|
|
|
|
return "unix";
|
|
|
|
default:
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-03-12 01:07:55 +08:00
|
|
|
SIGAR_DECLARE(const char *)sigar_net_connection_state_get(int state)
|
|
|
|
{
|
|
|
|
switch (state) {
|
|
|
|
case SIGAR_TCP_ESTABLISHED:
|
|
|
|
return "ESTABLISHED";
|
|
|
|
case SIGAR_TCP_SYN_SENT:
|
|
|
|
return "SYN_SENT";
|
|
|
|
case SIGAR_TCP_SYN_RECV:
|
|
|
|
return "SYN_RECV";
|
|
|
|
case SIGAR_TCP_FIN_WAIT1:
|
|
|
|
return "FIN_WAIT1";
|
|
|
|
case SIGAR_TCP_FIN_WAIT2:
|
|
|
|
return "FIN_WAIT2";
|
|
|
|
case SIGAR_TCP_TIME_WAIT:
|
|
|
|
return "TIME_WAIT";
|
|
|
|
case SIGAR_TCP_CLOSE:
|
|
|
|
return "CLOSE";
|
|
|
|
case SIGAR_TCP_CLOSE_WAIT:
|
|
|
|
return "CLOSE_WAIT";
|
|
|
|
case SIGAR_TCP_LAST_ACK:
|
|
|
|
return "LAST_ACK";
|
|
|
|
case SIGAR_TCP_LISTEN:
|
|
|
|
return "LISTEN";
|
|
|
|
case SIGAR_TCP_CLOSING:
|
|
|
|
return "CLOSING";
|
2005-03-12 10:17:20 +08:00
|
|
|
case SIGAR_TCP_IDLE:
|
|
|
|
return "IDLE";
|
|
|
|
case SIGAR_TCP_BOUND:
|
|
|
|
return "BOUND";
|
2005-03-12 01:11:07 +08:00
|
|
|
case SIGAR_TCP_UNKNOWN:
|
2005-03-12 01:07:55 +08:00
|
|
|
default:
|
|
|
|
return "UNKNOWN";
|
|
|
|
}
|
|
|
|
}
|
2006-07-02 00:47:47 +08:00
|
|
|
|
2006-07-02 03:11:54 +08:00
|
|
|
#if !defined(__linux__)
|
2006-07-02 00:47:47 +08:00
|
|
|
/*
|
|
|
|
* implement sigar_net_connection_list_get using sigar_net_connection_walk
|
2006-07-02 03:11:54 +08:00
|
|
|
* linux has its own list_get impl.
|
2006-07-02 00:47:47 +08:00
|
|
|
*/
|
|
|
|
static int net_connection_list_walker(sigar_net_connection_walker_t *walker,
|
|
|
|
sigar_net_connection_t *conn)
|
|
|
|
{
|
|
|
|
sigar_net_connection_list_t *connlist =
|
|
|
|
(sigar_net_connection_list_t *)walker->data;
|
|
|
|
|
|
|
|
SIGAR_NET_CONNLIST_GROW(connlist);
|
|
|
|
memcpy(&connlist->data[connlist->number++],
|
|
|
|
conn, sizeof(*conn));
|
|
|
|
|
|
|
|
return SIGAR_OK; /* continue loop */
|
|
|
|
}
|
|
|
|
|
2006-07-02 03:06:11 +08:00
|
|
|
SIGAR_DECLARE(int)
|
|
|
|
sigar_net_connection_list_get(sigar_t *sigar,
|
|
|
|
sigar_net_connection_list_t *connlist,
|
|
|
|
int flags)
|
2006-07-02 00:47:47 +08:00
|
|
|
{
|
|
|
|
int status;
|
|
|
|
sigar_net_connection_walker_t walker;
|
|
|
|
|
|
|
|
sigar_net_connection_list_create(connlist);
|
|
|
|
|
|
|
|
walker.sigar = sigar;
|
|
|
|
walker.flags = flags;
|
|
|
|
walker.data = connlist;
|
|
|
|
walker.add_connection = net_connection_list_walker;
|
|
|
|
|
|
|
|
status = sigar_net_connection_walk(&walker);
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
sigar_net_connection_list_destroy(sigar, connlist);
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
#endif
|
2006-07-02 03:14:32 +08:00
|
|
|
|
2006-06-20 08:30:17 +08:00
|
|
|
typedef struct {
|
|
|
|
sigar_net_stat_t *netstat;
|
|
|
|
sigar_cache_t *listen_ports;
|
|
|
|
sigar_net_connection_list_t *connlist;
|
|
|
|
} net_stat_getter_t;
|
2005-03-12 01:07:55 +08:00
|
|
|
|
2006-06-20 08:30:17 +08:00
|
|
|
static void listen_port_free(void *ptr)
|
|
|
|
{
|
|
|
|
/*noop*/
|
|
|
|
}
|
|
|
|
|
|
|
|
static int net_stat_walker(sigar_net_connection_walker_t *walker,
|
|
|
|
sigar_net_connection_t *conn)
|
|
|
|
{
|
|
|
|
int state = conn->state;
|
|
|
|
net_stat_getter_t *getter =
|
|
|
|
(net_stat_getter_t *)walker->data;
|
|
|
|
|
|
|
|
if (conn->type == SIGAR_NETCONN_TCP) {
|
|
|
|
getter->netstat->tcp_states[state]++;
|
|
|
|
|
|
|
|
if (state == SIGAR_TCP_LISTEN) {
|
|
|
|
sigar_cache_entry_t *entry =
|
|
|
|
sigar_cache_get(getter->listen_ports,
|
|
|
|
conn->local_port);
|
|
|
|
|
|
|
|
entry->value = (void*)conn->local_port;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (sigar_cache_find(getter->listen_ports,
|
|
|
|
conn->local_port))
|
|
|
|
{
|
|
|
|
getter->netstat->tcp_inbound_total++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
getter->netstat->tcp_outbound_total++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (conn->type == SIGAR_NETCONN_UDP) {
|
|
|
|
/*XXX*/
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
2006-07-11 05:32:22 +08:00
|
|
|
static int sigar_net_stat_get_walk(sigar_t *sigar,
|
|
|
|
sigar_net_stat_t *netstat,
|
|
|
|
int flags)
|
2006-06-20 08:30:17 +08:00
|
|
|
{
|
|
|
|
int status;
|
|
|
|
sigar_net_connection_walker_t walker;
|
|
|
|
net_stat_getter_t getter;
|
|
|
|
|
|
|
|
getter.netstat = netstat;
|
|
|
|
getter.listen_ports = sigar_cache_new(32);
|
|
|
|
getter.listen_ports->free_value = listen_port_free;
|
|
|
|
|
|
|
|
walker.sigar = sigar;
|
|
|
|
walker.data = &getter;
|
|
|
|
walker.add_connection = net_stat_walker;
|
|
|
|
|
|
|
|
walker.flags = flags;
|
|
|
|
|
|
|
|
status = sigar_net_connection_walk(&walker);
|
|
|
|
|
|
|
|
sigar_cache_destroy(getter.listen_ports);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
2006-07-02 03:14:32 +08:00
|
|
|
|
2006-07-11 05:32:22 +08:00
|
|
|
static int sigar_net_stat_get_list(sigar_t *sigar,
|
|
|
|
sigar_net_stat_t *netstat,
|
|
|
|
int flags)
|
|
|
|
{
|
|
|
|
int status, i;
|
|
|
|
sigar_net_connection_list_t connlist;
|
|
|
|
sigar_cache_t *listen_ports;
|
|
|
|
status = sigar_net_connection_list_get(sigar, &connlist, flags);
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
listen_ports = sigar_cache_new(32);
|
|
|
|
listen_ports->free_value = listen_port_free;
|
|
|
|
|
|
|
|
/* first pass, get states and listening port numbers */
|
|
|
|
for (i=0; i<connlist.number; i++) {
|
|
|
|
sigar_net_connection_t *conn = &connlist.data[i];
|
|
|
|
int state = conn->state;
|
|
|
|
|
|
|
|
netstat->tcp_states[state]++;
|
|
|
|
|
|
|
|
if (state == SIGAR_TCP_LISTEN) {
|
|
|
|
sigar_cache_entry_t *entry =
|
|
|
|
sigar_cache_get(listen_ports,
|
|
|
|
conn->local_port);
|
|
|
|
|
|
|
|
entry->value = (void*)conn->local_port;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* second pass, get addresses connected to listening ports */
|
|
|
|
for (i=0; i<connlist.number; i++) {
|
|
|
|
sigar_net_connection_t *conn = &connlist.data[i];
|
|
|
|
|
|
|
|
if (conn->state != SIGAR_TCP_LISTEN) {
|
|
|
|
if (sigar_cache_find(listen_ports,
|
|
|
|
conn->local_port))
|
|
|
|
{
|
|
|
|
netstat->tcp_inbound_total++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
netstat->tcp_outbound_total++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sigar_cache_destroy(listen_ports);
|
|
|
|
sigar_net_connection_list_destroy(sigar, &connlist);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_DECLARE(int)
|
|
|
|
sigar_net_stat_get(sigar_t *sigar,
|
|
|
|
sigar_net_stat_t *netstat,
|
|
|
|
int flags)
|
|
|
|
{
|
|
|
|
SIGAR_ZERO(netstat);
|
|
|
|
|
|
|
|
if (getenv("SIGAR_NETSTAT_WALK")) {
|
|
|
|
/* XXX only for testing atm
|
|
|
|
* The 'walk' version is faster that the 'list' version,
|
|
|
|
* however the 'walk' version depends on the underlying
|
|
|
|
* OS to return connections in the LISTEN state before
|
|
|
|
* those which are connected to the given LISTEN port.
|
|
|
|
* Seems this is the case in Linux at least, but that
|
|
|
|
* is likely subject to change.
|
|
|
|
*/
|
|
|
|
return sigar_net_stat_get_walk(sigar, netstat, flags);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return sigar_net_stat_get_list(sigar, netstat, flags);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-02-22 09:50:40 +08:00
|
|
|
int sigar_who_list_create(sigar_who_list_t *wholist)
|
|
|
|
{
|
|
|
|
wholist->number = 0;
|
|
|
|
wholist->size = SIGAR_WHO_LIST_MAX;
|
|
|
|
wholist->data = malloc(sizeof(*(wholist->data)) *
|
|
|
|
wholist->size);
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sigar_who_list_grow(sigar_who_list_t *wholist)
|
|
|
|
{
|
|
|
|
wholist->data = realloc(wholist->data,
|
|
|
|
sizeof(*(wholist->data)) *
|
|
|
|
(wholist->size + SIGAR_WHO_LIST_MAX));
|
|
|
|
wholist->size += SIGAR_WHO_LIST_MAX;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_DECLARE(int) sigar_who_list_destroy(sigar_t *sigar,
|
|
|
|
sigar_who_list_t *wholist)
|
|
|
|
{
|
|
|
|
if (wholist->size) {
|
|
|
|
free(wholist->data);
|
|
|
|
wholist->number = wholist->size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
2005-07-24 14:00:13 +08:00
|
|
|
#if defined(__sun)
|
|
|
|
# include <utmpx.h>
|
|
|
|
# define SIGAR_UTMP_FILE _UTMPX_FILE
|
|
|
|
# define ut_time ut_tv.tv_sec
|
|
|
|
#elif defined(WIN32)
|
|
|
|
/* XXX may not be the default */
|
|
|
|
#define SIGAR_UTMP_FILE "C:\\cygwin\\var\\run\\utmp"
|
|
|
|
#define UT_LINESIZE 16
|
|
|
|
#define UT_NAMESIZE 16
|
|
|
|
#define UT_HOSTSIZE 256
|
|
|
|
#define UT_IDLEN 2
|
|
|
|
#define ut_name ut_user
|
|
|
|
|
|
|
|
struct utmp {
|
|
|
|
short ut_type;
|
2005-07-24 14:03:07 +08:00
|
|
|
int ut_pid;
|
2005-07-24 14:00:13 +08:00
|
|
|
char ut_line[UT_LINESIZE];
|
|
|
|
char ut_id[UT_IDLEN];
|
|
|
|
time_t ut_time;
|
|
|
|
char ut_user[UT_NAMESIZE];
|
|
|
|
char ut_host[UT_HOSTSIZE];
|
|
|
|
long ut_addr;
|
|
|
|
};
|
2005-08-18 12:22:53 +08:00
|
|
|
#elif defined(NETWARE)
|
2005-08-28 14:18:35 +08:00
|
|
|
static char *getpass(const char *prompt)
|
|
|
|
{
|
|
|
|
static char password[BUFSIZ];
|
|
|
|
|
|
|
|
fputs(prompt, stderr);
|
|
|
|
fgets((char *)&password, sizeof(password), stdin);
|
|
|
|
|
|
|
|
return (char *)&password;
|
|
|
|
}
|
2005-07-24 14:00:13 +08:00
|
|
|
#else
|
|
|
|
# include <utmp.h>
|
|
|
|
# ifdef UTMP_FILE
|
|
|
|
# define SIGAR_UTMP_FILE UTMP_FILE
|
|
|
|
# else
|
|
|
|
# define SIGAR_UTMP_FILE _PATH_UTMP
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(__FreeBSD__) || defined(DARWIN)
|
|
|
|
# define ut_user ut_name
|
|
|
|
#endif
|
|
|
|
|
2005-09-25 06:37:21 +08:00
|
|
|
#if !defined(NETWARE) && !defined(_AIX)
|
2005-08-18 12:22:53 +08:00
|
|
|
|
2005-07-24 14:00:13 +08:00
|
|
|
#define WHOCPY(dest, src) \
|
|
|
|
SIGAR_SSTRCPY(dest, src); \
|
|
|
|
if (sizeof(src) < sizeof(dest)) \
|
|
|
|
dest[sizeof(src)] = '\0'
|
|
|
|
|
|
|
|
static int sigar_who_utmp(sigar_t *sigar,
|
|
|
|
sigar_who_list_t *wholist)
|
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
#ifdef __sun
|
2007-01-18 02:48:36 +08:00
|
|
|
/* use futmpx w/ pid32_t for sparc64 */
|
|
|
|
struct futmpx ut;
|
2005-07-24 14:00:13 +08:00
|
|
|
#else
|
|
|
|
struct utmp ut;
|
|
|
|
#endif
|
|
|
|
if (!(fp = fopen(SIGAR_UTMP_FILE, "r"))) {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (fread(&ut, sizeof(ut), 1, fp) == 1) {
|
|
|
|
sigar_who_t *who;
|
|
|
|
|
|
|
|
if (*ut.ut_name == '\0') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef USER_PROCESS
|
|
|
|
if (ut.ut_type != USER_PROCESS) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
SIGAR_WHO_LIST_GROW(wholist);
|
|
|
|
who = &wholist->data[wholist->number++];
|
|
|
|
|
|
|
|
WHOCPY(who->user, ut.ut_user);
|
|
|
|
WHOCPY(who->device, ut.ut_line);
|
|
|
|
WHOCPY(who->host, ut.ut_host);
|
|
|
|
|
|
|
|
who->time = ut.ut_time;
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
2005-08-18 12:22:53 +08:00
|
|
|
#endif /* NETWARE */
|
|
|
|
|
|
|
|
#if defined(WIN32)
|
2005-07-24 09:34:27 +08:00
|
|
|
|
2005-09-27 07:35:57 +08:00
|
|
|
int sigar_who_list_get_win32(sigar_t *sigar,
|
|
|
|
sigar_who_list_t *wholist);
|
2005-07-24 13:00:24 +08:00
|
|
|
|
2005-02-22 09:50:40 +08:00
|
|
|
SIGAR_DECLARE(int) sigar_who_list_get(sigar_t *sigar,
|
|
|
|
sigar_who_list_t *wholist)
|
|
|
|
{
|
2005-07-24 09:34:27 +08:00
|
|
|
sigar_who_list_create(wholist);
|
|
|
|
|
2005-07-24 14:00:13 +08:00
|
|
|
/* cygwin ssh */
|
|
|
|
sigar_who_utmp(sigar, wholist);
|
|
|
|
|
2005-09-27 07:35:57 +08:00
|
|
|
sigar_who_list_get_win32(sigar, wholist);
|
|
|
|
|
2005-07-24 09:34:27 +08:00
|
|
|
return SIGAR_OK;
|
2005-02-22 09:50:40 +08:00
|
|
|
}
|
2005-07-08 09:03:42 +08:00
|
|
|
|
|
|
|
SIGAR_DECLARE(int) sigar_resource_limit_get(sigar_t *sigar,
|
|
|
|
sigar_resource_limit_t *rlimit)
|
|
|
|
{
|
2005-07-08 09:49:18 +08:00
|
|
|
MEMORY_BASIC_INFORMATION meminfo;
|
2005-07-22 07:34:36 +08:00
|
|
|
memset(rlimit, 0x7fffffff, sizeof(*rlimit));
|
2005-07-08 09:49:18 +08:00
|
|
|
|
|
|
|
if (VirtualQuery((LPCVOID)&meminfo, &meminfo, sizeof(meminfo))) {
|
|
|
|
rlimit->stack_cur =
|
|
|
|
(DWORD)&meminfo - (DWORD)meminfo.AllocationBase;
|
|
|
|
rlimit->stack_max =
|
|
|
|
((DWORD)meminfo.BaseAddress + meminfo.RegionSize) -
|
|
|
|
(DWORD)meminfo.AllocationBase;
|
|
|
|
}
|
|
|
|
|
|
|
|
rlimit->virtual_memory_max = rlimit->virtual_memory_cur =
|
|
|
|
0x80000000UL;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
2005-07-08 09:03:42 +08:00
|
|
|
}
|
2005-08-18 12:22:53 +08:00
|
|
|
|
|
|
|
#elif defined(NETWARE)
|
2005-08-28 13:47:48 +08:00
|
|
|
int sigar_resource_limit_get(sigar_t *sigar,
|
|
|
|
sigar_resource_limit_t *rlimit)
|
|
|
|
{
|
|
|
|
return SIGAR_ENOTIMPL;
|
|
|
|
}
|
2005-08-28 13:59:53 +08:00
|
|
|
|
|
|
|
int sigar_who_list_get(sigar_t *sigar,
|
|
|
|
sigar_who_list_t *wholist)
|
|
|
|
{
|
|
|
|
return SIGAR_ENOTIMPL;
|
|
|
|
}
|
2005-02-22 09:50:40 +08:00
|
|
|
#else
|
2005-02-22 10:05:26 +08:00
|
|
|
|
2005-09-25 06:37:21 +08:00
|
|
|
#ifndef _AIX
|
2005-02-22 09:50:40 +08:00
|
|
|
int sigar_who_list_get(sigar_t *sigar,
|
|
|
|
sigar_who_list_t *wholist)
|
|
|
|
{
|
2005-07-24 14:00:13 +08:00
|
|
|
int status;
|
2005-02-22 09:50:40 +08:00
|
|
|
|
|
|
|
sigar_who_list_create(wholist);
|
|
|
|
|
2005-07-24 14:00:13 +08:00
|
|
|
status = sigar_who_utmp(sigar, wholist);
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
sigar_who_list_destroy(sigar, wholist);
|
|
|
|
return status;
|
2005-02-22 09:50:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
2005-09-25 06:37:21 +08:00
|
|
|
#endif
|
2005-07-08 09:03:42 +08:00
|
|
|
|
2005-07-14 09:01:32 +08:00
|
|
|
static int sigar_get_default_gateway(sigar_t *sigar,
|
|
|
|
char *gateway)
|
|
|
|
{
|
|
|
|
int status, i;
|
|
|
|
sigar_net_route_list_t routelist;
|
|
|
|
|
|
|
|
status = sigar_net_route_list_get(sigar, &routelist);
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=0; i<routelist.number; i++) {
|
2006-06-10 01:42:46 +08:00
|
|
|
if ((routelist.data[i].flags & SIGAR_RTF_GATEWAY) &&
|
2006-07-05 03:22:05 +08:00
|
|
|
(routelist.data[i].destination.addr.in == 0))
|
2006-06-10 01:42:46 +08:00
|
|
|
{
|
2006-07-05 03:22:05 +08:00
|
|
|
sigar_net_address_to_string(sigar,
|
|
|
|
&routelist.data[i].gateway,
|
|
|
|
gateway);
|
2005-07-14 09:01:32 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sigar_net_route_list_destroy(sigar, &routelist);
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
2005-07-12 04:21:13 +08:00
|
|
|
int sigar_net_info_get(sigar_t *sigar,
|
|
|
|
sigar_net_info_t *netinfo)
|
|
|
|
{
|
2005-07-12 04:41:57 +08:00
|
|
|
int size;
|
2005-07-12 04:21:13 +08:00
|
|
|
char buffer[BUFSIZ], *ptr;
|
|
|
|
FILE *fp;
|
|
|
|
|
|
|
|
if (!(fp = fopen("/etc/resolv.conf", "r"))) {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_ZERO(netinfo);
|
|
|
|
|
|
|
|
while ((ptr = fgets(buffer, sizeof(buffer), fp))) {
|
|
|
|
int len;
|
|
|
|
|
|
|
|
SIGAR_SKIP_SPACE(ptr);
|
2006-07-16 08:01:25 +08:00
|
|
|
if (!(ptr = strstr(ptr, "nameserver"))) {
|
2005-07-12 04:21:13 +08:00
|
|
|
continue;
|
|
|
|
}
|
2006-07-16 08:01:25 +08:00
|
|
|
ptr += 10;
|
2005-07-12 04:21:13 +08:00
|
|
|
SIGAR_SKIP_SPACE(ptr);
|
|
|
|
|
|
|
|
len = strlen(ptr);
|
|
|
|
ptr[len-1] = '\0'; /* chop \n */
|
|
|
|
|
|
|
|
if (!netinfo->primary_dns[0]) {
|
|
|
|
SIGAR_SSTRCPY(netinfo->primary_dns, ptr);
|
|
|
|
}
|
|
|
|
else if (!netinfo->secondary_dns[0]) {
|
|
|
|
SIGAR_SSTRCPY(netinfo->secondary_dns, ptr);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
|
2005-07-12 06:45:50 +08:00
|
|
|
size = sizeof(netinfo->host_name)-1;
|
|
|
|
if (gethostname(netinfo->host_name, size) == 0) {
|
|
|
|
netinfo->host_name[size] = '\0';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
netinfo->host_name[0] = '\0';
|
|
|
|
}
|
|
|
|
|
2005-07-12 04:41:57 +08:00
|
|
|
size = sizeof(netinfo->domain_name)-1;
|
|
|
|
if (getdomainname(netinfo->domain_name, size) == 0) {
|
|
|
|
netinfo->domain_name[size] = '\0';
|
2005-07-12 04:37:47 +08:00
|
|
|
}
|
|
|
|
else {
|
2005-07-12 04:41:57 +08:00
|
|
|
netinfo->domain_name[0] = '\0';
|
2005-07-12 04:37:47 +08:00
|
|
|
}
|
2005-07-12 04:29:38 +08:00
|
|
|
|
2005-07-14 09:01:32 +08:00
|
|
|
sigar_get_default_gateway(sigar, netinfo->default_gateway);
|
|
|
|
|
2005-07-12 04:21:13 +08:00
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
2005-07-08 09:03:42 +08:00
|
|
|
#include <sys/resource.h>
|
|
|
|
|
|
|
|
#define OffsetOf(structure, field) \
|
|
|
|
(size_t)(&((structure *)NULL)->field)
|
|
|
|
|
|
|
|
#define RlimitOffsets(field) \
|
|
|
|
OffsetOf(sigar_resource_limit_t, field##_cur), \
|
|
|
|
OffsetOf(sigar_resource_limit_t, field##_max)
|
|
|
|
|
|
|
|
#define RlimitSet(structure, ptr, val) \
|
|
|
|
*(sigar_uint64_t *)((char *)structure + (int)(long)ptr) = val
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int resource;
|
2005-07-22 06:19:03 +08:00
|
|
|
int factor;
|
2005-07-08 09:03:42 +08:00
|
|
|
size_t cur;
|
|
|
|
size_t max;
|
|
|
|
} rlimit_field_t;
|
|
|
|
|
|
|
|
#ifndef RLIMIT_RSS
|
2005-07-22 06:46:57 +08:00
|
|
|
#define RLIMIT_RSS (RLIM_NLIMITS+1)
|
2005-07-08 09:03:42 +08:00
|
|
|
#endif
|
|
|
|
|
2005-07-08 09:51:00 +08:00
|
|
|
#ifndef RLIMIT_NPROC
|
2005-07-22 06:46:57 +08:00
|
|
|
#define RLIMIT_NPROC (RLIM_NLIMITS+2)
|
2005-07-08 09:51:00 +08:00
|
|
|
#endif
|
|
|
|
|
2005-07-22 10:26:48 +08:00
|
|
|
#define RLIMIT_PSIZE (RLIM_NLIMITS+3)
|
|
|
|
|
2006-01-01 02:43:09 +08:00
|
|
|
#ifndef RLIMIT_AS
|
|
|
|
#define RLIMIT_AS RLIMIT_VMEM
|
|
|
|
#endif
|
|
|
|
|
2005-07-08 09:03:42 +08:00
|
|
|
static rlimit_field_t sigar_rlimits[] = {
|
2005-07-22 06:19:03 +08:00
|
|
|
{ RLIMIT_CPU, 1, RlimitOffsets(cpu) },
|
|
|
|
{ RLIMIT_FSIZE, 1024, RlimitOffsets(file_size) },
|
|
|
|
{ RLIMIT_DATA, 1024, RlimitOffsets(data) },
|
|
|
|
{ RLIMIT_STACK, 1024, RlimitOffsets(stack) },
|
2005-07-22 10:26:48 +08:00
|
|
|
{ RLIMIT_PSIZE, 512, RlimitOffsets(pipe_size) },
|
2005-07-22 06:19:03 +08:00
|
|
|
{ RLIMIT_CORE, 1024, RlimitOffsets(core) },
|
|
|
|
{ RLIMIT_RSS, 1024, RlimitOffsets(memory) },
|
|
|
|
{ RLIMIT_NPROC, 1, RlimitOffsets(processes) },
|
|
|
|
{ RLIMIT_NOFILE, 1, RlimitOffsets(open_files) },
|
|
|
|
{ RLIMIT_AS, 1024, RlimitOffsets(virtual_memory) },
|
2005-07-08 09:03:42 +08:00
|
|
|
{ -1 }
|
|
|
|
};
|
|
|
|
|
2005-07-22 06:19:03 +08:00
|
|
|
#define RlimitScale(val) \
|
|
|
|
if (val != RLIM_INFINITY) val /= r->factor
|
|
|
|
|
2005-07-22 06:46:57 +08:00
|
|
|
#define RlimitHS(val) \
|
|
|
|
rl.rlim_cur = rl.rlim_max = (val)
|
|
|
|
|
2005-07-08 09:03:42 +08:00
|
|
|
int sigar_resource_limit_get(sigar_t *sigar,
|
|
|
|
sigar_resource_limit_t *rlimit)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i=0; sigar_rlimits[i].resource != -1; i++) {
|
|
|
|
struct rlimit rl;
|
|
|
|
rlimit_field_t *r = &sigar_rlimits[i];
|
|
|
|
|
2005-07-22 06:46:57 +08:00
|
|
|
if (r->resource > RLIM_NLIMITS) {
|
|
|
|
switch (r->resource) {
|
|
|
|
case RLIMIT_NPROC:
|
|
|
|
RlimitHS(sysconf(_SC_CHILD_MAX));
|
|
|
|
break;
|
2005-07-22 10:26:48 +08:00
|
|
|
case RLIMIT_PSIZE:
|
|
|
|
RlimitHS(PIPE_BUF/512);
|
|
|
|
break;
|
2005-07-22 06:46:57 +08:00
|
|
|
default:
|
|
|
|
RlimitHS(RLIM_INFINITY);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (getrlimit(r->resource, &rl) != 0) {
|
|
|
|
RlimitHS(RLIM_INFINITY);
|
2005-07-22 06:28:07 +08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
RlimitScale(rl.rlim_cur);
|
|
|
|
RlimitScale(rl.rlim_max);
|
2005-07-08 09:03:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
RlimitSet(rlimit, r->cur, rl.rlim_cur);
|
|
|
|
RlimitSet(rlimit, r->max, rl.rlim_max);
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
2005-02-22 09:50:40 +08:00
|
|
|
#endif
|
|
|
|
|
2005-08-18 12:22:53 +08:00
|
|
|
#if !defined(WIN32) && !defined(DARWIN) && !defined(__FreeBSD__) && !defined(NETWARE)
|
2004-06-22 06:37:04 +08:00
|
|
|
|
|
|
|
/* XXX: prolly will be moving these stuffs into os_net.c */
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <net/if.h>
|
|
|
|
|
|
|
|
#ifndef SIOCGIFCONF
|
|
|
|
#include <sys/sockio.h>
|
|
|
|
#endif
|
|
|
|
|
2004-10-02 11:45:13 +08:00
|
|
|
#if defined(_AIX) || defined(__osf__) /* good buddies */
|
2004-06-22 06:37:04 +08:00
|
|
|
|
|
|
|
#include <net/if_dl.h>
|
|
|
|
|
|
|
|
static void hwaddr_aix_lookup(sigar_t *sigar, sigar_net_interface_config_t *ifconfig)
|
|
|
|
{
|
|
|
|
char *ent, *end;
|
|
|
|
struct ifreq *ifr;
|
|
|
|
|
|
|
|
/* XXX: assumes sigar_net_interface_list_get has been called */
|
|
|
|
end = sigar->ifconf_buf + sigar->ifconf_len;
|
|
|
|
|
|
|
|
for (ent = sigar->ifconf_buf;
|
|
|
|
ent < end;
|
|
|
|
ent += sizeof(*ifr))
|
|
|
|
{
|
|
|
|
ifr = (struct ifreq *)ent;
|
|
|
|
|
|
|
|
if (ifr->ifr_addr.sa_family != AF_LINK) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strEQ(ifr->ifr_name, ifconfig->name)) {
|
|
|
|
struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
|
|
|
|
|
2006-07-06 05:33:59 +08:00
|
|
|
sigar_net_address_mac_set(ifconfig->hwaddr,
|
|
|
|
LLADDR(sdl),
|
|
|
|
sdl->sdl_alen);
|
2004-06-22 06:37:04 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sigar_hwaddr_set_null(ifconfig);
|
|
|
|
}
|
|
|
|
|
|
|
|
#elif !defined(SIOCGIFHWADDR)
|
|
|
|
|
|
|
|
#include <net/if_arp.h>
|
|
|
|
|
|
|
|
static void hwaddr_arp_lookup(sigar_net_interface_config_t *ifconfig, int sock)
|
|
|
|
{
|
|
|
|
struct arpreq areq;
|
|
|
|
struct sockaddr_in *sa;
|
|
|
|
|
|
|
|
memset(&areq, 0, sizeof(areq));
|
|
|
|
sa = (struct sockaddr_in *)&areq.arp_pa;
|
|
|
|
sa->sin_family = AF_INET;
|
2006-07-05 01:38:14 +08:00
|
|
|
sa->sin_addr.s_addr = ifconfig->address.addr.in;
|
2004-06-22 06:37:04 +08:00
|
|
|
|
|
|
|
if (ioctl(sock, SIOCGARP, &areq) < 0) {
|
|
|
|
/* ho-hum */
|
2006-07-06 05:33:59 +08:00
|
|
|
sigar_hwaddr_set_null(ifconfig);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sigar_net_address_mac_set(ifconfig->hwaddr,
|
|
|
|
areq.arp_ha.sa_data,
|
|
|
|
SIGAR_IFHWADDRLEN);
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2005-11-19 02:08:19 +08:00
|
|
|
#ifdef __linux__
|
|
|
|
|
|
|
|
#include <net/if_arp.h>
|
|
|
|
|
|
|
|
static void get_interface_type(sigar_net_interface_config_t *ifconfig,
|
|
|
|
int family)
|
|
|
|
{
|
|
|
|
char *type;
|
|
|
|
|
|
|
|
switch (family) {
|
|
|
|
case ARPHRD_NETROM:
|
2005-11-19 03:54:23 +08:00
|
|
|
type = SIGAR_NIC_NETROM;
|
2005-11-19 02:08:19 +08:00
|
|
|
break;
|
|
|
|
/* XXX more */
|
|
|
|
default:
|
2005-11-19 03:54:23 +08:00
|
|
|
type = SIGAR_NIC_ETHERNET;
|
2005-11-19 02:08:19 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_SSTRCPY(ifconfig->type, type);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
int sigar_net_interface_config_get(sigar_t *sigar, const char *name,
|
|
|
|
sigar_net_interface_config_t *ifconfig)
|
|
|
|
{
|
|
|
|
int sock;
|
|
|
|
struct ifreq ifr;
|
|
|
|
|
2007-04-05 23:41:43 +08:00
|
|
|
if (!name) {
|
|
|
|
return sigar_net_interface_config_primary_get(sigar, ifconfig);
|
|
|
|
}
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
SIGAR_ZERO(ifconfig);
|
|
|
|
|
|
|
|
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_SSTRCPY(ifconfig->name, name);
|
|
|
|
SIGAR_SSTRCPY(ifr.ifr_name, name);
|
|
|
|
|
|
|
|
#define ifr_s_addr(ifr) \
|
|
|
|
((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr
|
|
|
|
|
|
|
|
if (!ioctl(sock, SIOCGIFADDR, &ifr)) {
|
2006-07-05 01:32:08 +08:00
|
|
|
sigar_net_address_set(ifconfig->address,
|
|
|
|
ifr_s_addr(ifr));
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!ioctl(sock, SIOCGIFNETMASK, &ifr)) {
|
2006-07-05 01:32:08 +08:00
|
|
|
sigar_net_address_set(ifconfig->netmask,
|
|
|
|
ifr_s_addr(ifr));
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!ioctl(sock, SIOCGIFFLAGS, &ifr)) {
|
2005-11-19 02:26:52 +08:00
|
|
|
sigar_uint64_t flags = ifr.ifr_flags;
|
2004-06-22 06:37:04 +08:00
|
|
|
#ifdef __linux__
|
2005-11-19 02:26:52 +08:00
|
|
|
int is_mcast = flags & IFF_MULTICAST;
|
|
|
|
int is_slave = flags & IFF_SLAVE;
|
2004-06-22 06:37:04 +08:00
|
|
|
/*
|
|
|
|
* XXX: should just define SIGAR_IFF_*
|
|
|
|
* and test IFF_* bits on given platform.
|
|
|
|
* this is the only diff between solaris/hpux/linux
|
|
|
|
* for the flags we care about.
|
|
|
|
*
|
|
|
|
*/
|
2005-11-19 02:26:52 +08:00
|
|
|
flags &= ~(IFF_MULTICAST|IFF_SLAVE);
|
|
|
|
if (is_mcast) {
|
|
|
|
flags |= SIGAR_IFF_MULTICAST;
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
2005-11-19 02:26:52 +08:00
|
|
|
if (is_slave) {
|
|
|
|
flags |= SIGAR_IFF_SLAVE;
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
#endif
|
2005-11-19 02:26:52 +08:00
|
|
|
ifconfig->flags = flags;
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* should always be able to get flags for existing device */
|
|
|
|
/* other ioctls may fail if device is not enabled: ok */
|
|
|
|
close(sock);
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ifconfig->flags & IFF_LOOPBACK) {
|
2006-07-05 01:32:08 +08:00
|
|
|
sigar_net_address_set(ifconfig->destination,
|
|
|
|
ifconfig->address.addr.in);
|
|
|
|
sigar_net_address_set(ifconfig->broadcast, 0);
|
2004-06-22 06:37:04 +08:00
|
|
|
sigar_hwaddr_set_null(ifconfig);
|
2005-11-19 03:54:23 +08:00
|
|
|
SIGAR_SSTRCPY(ifconfig->type,
|
|
|
|
SIGAR_NIC_LOOPBACK);
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!ioctl(sock, SIOCGIFDSTADDR, &ifr)) {
|
2006-07-05 01:32:08 +08:00
|
|
|
sigar_net_address_set(ifconfig->destination,
|
|
|
|
ifr_s_addr(ifr));
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!ioctl(sock, SIOCGIFBRDADDR, &ifr)) {
|
2006-07-05 01:32:08 +08:00
|
|
|
sigar_net_address_set(ifconfig->broadcast,
|
|
|
|
ifr_s_addr(ifr));
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(SIOCGIFHWADDR)
|
|
|
|
if (!ioctl(sock, SIOCGIFHWADDR, &ifr)) {
|
2005-11-19 02:08:19 +08:00
|
|
|
get_interface_type(ifconfig,
|
|
|
|
ifr.ifr_hwaddr.sa_family);
|
2006-07-06 05:33:59 +08:00
|
|
|
sigar_net_address_mac_set(ifconfig->hwaddr,
|
|
|
|
ifr.ifr_hwaddr.sa_data,
|
|
|
|
IFHWADDRLEN);
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
2004-10-02 11:45:13 +08:00
|
|
|
#elif defined(_AIX) || defined(__osf__)
|
2004-06-22 06:37:04 +08:00
|
|
|
hwaddr_aix_lookup(sigar, ifconfig);
|
2005-11-19 03:54:23 +08:00
|
|
|
SIGAR_SSTRCPY(ifconfig->type,
|
|
|
|
SIGAR_NIC_ETHERNET);
|
2004-06-22 06:37:04 +08:00
|
|
|
#else
|
|
|
|
hwaddr_arp_lookup(ifconfig, sock);
|
2005-11-19 03:54:23 +08:00
|
|
|
SIGAR_SSTRCPY(ifconfig->type,
|
|
|
|
SIGAR_NIC_ETHERNET);
|
2004-06-22 06:37:04 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2005-12-20 06:00:39 +08:00
|
|
|
#if defined(SIOCGLIFMTU) && !defined(__hpux)
|
|
|
|
{
|
|
|
|
struct lifreq lifr;
|
|
|
|
SIGAR_SSTRCPY(lifr.lifr_name, name);
|
|
|
|
if(!ioctl(sock, SIOCGLIFMTU, &lifr)) {
|
|
|
|
ifconfig->mtu = lifr.lifr_mtu;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#elif defined(SIOCGIFMTU)
|
2004-06-22 06:37:04 +08:00
|
|
|
if (!ioctl(sock, SIOCGIFMTU, &ifr)) {
|
2005-12-20 06:00:39 +08:00
|
|
|
# if defined(__hpux)
|
|
|
|
ifconfig->mtu = ifr.ifr_metric;
|
|
|
|
# else
|
2004-06-22 06:37:04 +08:00
|
|
|
ifconfig->mtu = ifr.ifr_mtu;
|
2005-12-20 06:00:39 +08:00
|
|
|
#endif
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
ifconfig->mtu = 0; /*XXX*/
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!ioctl(sock, SIOCGIFMETRIC, &ifr)) {
|
|
|
|
ifconfig->metric = ifr.ifr_metric ? ifr.ifr_metric : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
close(sock);
|
|
|
|
|
2006-03-05 06:28:09 +08:00
|
|
|
/* XXX can we get a better description like win32? */
|
|
|
|
SIGAR_SSTRCPY(ifconfig->description,
|
|
|
|
ifconfig->name);
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef _AIX
|
|
|
|
# define MY_SIOCGIFCONF CSIOCGIFCONF
|
|
|
|
#else
|
|
|
|
# define MY_SIOCGIFCONF SIOCGIFCONF
|
|
|
|
#endif
|
|
|
|
|
2004-10-02 11:39:23 +08:00
|
|
|
#ifdef __osf__
|
|
|
|
static int sigar_netif_configured(sigar_t *sigar, char *name)
|
|
|
|
{
|
|
|
|
int status;
|
|
|
|
sigar_net_interface_config_t ifconfig;
|
|
|
|
|
|
|
|
status = sigar_net_interface_config_get(sigar, name, &ifconfig);
|
|
|
|
|
|
|
|
return status == SIGAR_OK;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-11-18 09:15:54 +08:00
|
|
|
#ifdef __linux__
|
|
|
|
static SIGAR_INLINE int has_interface(sigar_net_interface_list_t *iflist,
|
|
|
|
char *name)
|
|
|
|
{
|
|
|
|
register int i;
|
|
|
|
register int num = iflist->number;
|
|
|
|
register char **data = iflist->data;
|
|
|
|
for (i=0; i<num; i++) {
|
|
|
|
if (strEQ(name, data[i])) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int proc_net_interface_list_get(sigar_t *sigar,
|
|
|
|
sigar_net_interface_list_t *iflist)
|
|
|
|
{
|
|
|
|
/* certain interfaces such as VMware vmnic
|
|
|
|
* are not returned by ioctl(SIOCGIFCONF).
|
|
|
|
* check /proc/net/dev for any ioctl missed.
|
|
|
|
*/
|
|
|
|
char buffer[BUFSIZ];
|
|
|
|
FILE *fp = fopen("/proc/net/dev", "r");
|
|
|
|
|
|
|
|
if (!fp) {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* skip header */
|
|
|
|
fgets(buffer, sizeof(buffer), fp);
|
|
|
|
fgets(buffer, sizeof(buffer), fp);
|
|
|
|
|
|
|
|
while (fgets(buffer, sizeof(buffer), fp)) {
|
|
|
|
char *ptr, *dev;
|
|
|
|
|
|
|
|
dev = buffer;
|
|
|
|
while (isspace(*dev)) {
|
|
|
|
dev++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(ptr = strchr(dev, ':'))) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
*ptr++ = 0;
|
|
|
|
|
|
|
|
if (has_interface(iflist, dev)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
SIGAR_NET_IFLIST_GROW(iflist);
|
|
|
|
|
|
|
|
iflist->data[iflist->number++] =
|
|
|
|
sigar_strdup(dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
int sigar_net_interface_list_get(sigar_t *sigar,
|
|
|
|
sigar_net_interface_list_t *iflist)
|
|
|
|
{
|
|
|
|
int n, lastlen=0;
|
|
|
|
struct ifreq *ifr;
|
|
|
|
struct ifconf ifc;
|
|
|
|
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
|
|
|
|
if (sock < 0) {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
if (!sigar->ifconf_buf || lastlen) {
|
|
|
|
sigar->ifconf_len += sizeof(struct ifreq) * SIGAR_NET_IFLIST_MAX;
|
|
|
|
sigar->ifconf_buf = realloc(sigar->ifconf_buf, sigar->ifconf_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
ifc.ifc_len = sigar->ifconf_len;
|
|
|
|
ifc.ifc_buf = sigar->ifconf_buf;
|
|
|
|
|
|
|
|
if (ioctl(sock, MY_SIOCGIFCONF, &ifc) < 0) {
|
|
|
|
/* EINVAL should mean num_interfaces > ifc.ifc_len */
|
|
|
|
if ((errno != EINVAL) ||
|
|
|
|
(lastlen == ifc.ifc_len))
|
|
|
|
{
|
|
|
|
free(ifc.ifc_buf);
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ifc.ifc_len < sigar->ifconf_len) {
|
|
|
|
break; /* got em all */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ifc.ifc_len != lastlen) {
|
|
|
|
/* might be more */
|
|
|
|
lastlen = ifc.ifc_len;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
close(sock);
|
|
|
|
|
|
|
|
iflist->number = 0;
|
|
|
|
iflist->size = ifc.ifc_len;
|
|
|
|
iflist->data = malloc(sizeof(*(iflist->data)) *
|
|
|
|
iflist->size);
|
|
|
|
|
|
|
|
ifr = ifc.ifc_req;
|
|
|
|
for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq), ifr++) {
|
2004-09-06 11:53:09 +08:00
|
|
|
#if defined(_AIX) || defined(__osf__) /* pass the bourbon */
|
2004-06-22 06:37:04 +08:00
|
|
|
if (ifr->ifr_addr.sa_family != AF_LINK) {
|
|
|
|
/* XXX: dunno if this is right.
|
|
|
|
* otherwise end up with two 'en0' and three 'lo0'
|
|
|
|
* with the same ip address.
|
|
|
|
*/
|
|
|
|
continue;
|
|
|
|
}
|
2004-10-02 11:39:23 +08:00
|
|
|
# ifdef __osf__
|
|
|
|
/* weed out "sl0", "tun0" and the like */
|
|
|
|
/* XXX must be a better way to check this */
|
|
|
|
if (!sigar_netif_configured(sigar, ifr->ifr_name)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
# endif
|
2004-06-22 06:37:04 +08:00
|
|
|
#endif
|
2005-11-10 02:26:10 +08:00
|
|
|
iflist->data[iflist->number++] =
|
|
|
|
sigar_strdup(ifr->ifr_name);
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
|
2005-11-18 09:15:54 +08:00
|
|
|
#ifdef __linux__
|
|
|
|
proc_net_interface_list_get(sigar, iflist);
|
|
|
|
#endif
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* WIN32 */
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* threadsafe alternative to inet_ntoa (inet_ntop4 from apr) */
|
2006-07-06 02:11:25 +08:00
|
|
|
static int sigar_inet_ntoa(sigar_t *sigar,
|
|
|
|
sigar_uint32_t address,
|
|
|
|
char *addr_str)
|
2004-06-22 06:37:04 +08:00
|
|
|
{
|
|
|
|
char *next=addr_str;
|
|
|
|
int n=0;
|
2006-07-06 02:11:25 +08:00
|
|
|
const unsigned char *src =
|
|
|
|
(const unsigned char *)&address;
|
2004-06-22 06:37:04 +08:00
|
|
|
|
|
|
|
do {
|
|
|
|
unsigned char u = *src++;
|
|
|
|
if (u > 99) {
|
|
|
|
*next++ = '0' + u/100;
|
|
|
|
u %= 100;
|
|
|
|
*next++ = '0' + u/10;
|
|
|
|
u %= 10;
|
|
|
|
}
|
|
|
|
else if (u > 9) {
|
|
|
|
*next++ = '0' + u/10;
|
|
|
|
u %= 10;
|
|
|
|
}
|
|
|
|
*next++ = '0' + u;
|
|
|
|
*next++ = '.';
|
|
|
|
n++;
|
|
|
|
} while (n < 4);
|
|
|
|
|
|
|
|
*--next = 0;
|
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
2006-07-06 05:33:59 +08:00
|
|
|
static int sigar_ether_ntoa(char *buff, unsigned char *ptr)
|
|
|
|
{
|
|
|
|
sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X",
|
|
|
|
(ptr[0] & 0xff), (ptr[1] & 0xff), (ptr[2] & 0xff),
|
|
|
|
(ptr[3] & 0xff), (ptr[4] & 0xff), (ptr[5] & 0xff));
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
2006-07-05 00:35:27 +08:00
|
|
|
SIGAR_DECLARE(int) sigar_net_address_to_string(sigar_t *sigar,
|
|
|
|
sigar_net_address_t *address,
|
|
|
|
char *addr_str)
|
|
|
|
{
|
|
|
|
switch (address->family) {
|
|
|
|
case SIGAR_AF_INET6:
|
|
|
|
#if defined(__linux__) /*XXX*/
|
|
|
|
if (inet_ntop(AF_INET6, (const void *)&address->addr.in6,
|
2006-10-20 04:10:13 +08:00
|
|
|
addr_str, SIGAR_INET6_ADDRSTRLEN))
|
2006-07-05 00:35:27 +08:00
|
|
|
{
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
case SIGAR_AF_INET:
|
|
|
|
return sigar_inet_ntoa(sigar, address->addr.in, addr_str);
|
|
|
|
case SIGAR_AF_UNSPEC:
|
2006-07-05 01:32:08 +08:00
|
|
|
return sigar_inet_ntoa(sigar, 0, addr_str); /*XXX*/
|
2006-07-06 05:12:10 +08:00
|
|
|
case SIGAR_AF_LINK:
|
2006-07-06 05:33:59 +08:00
|
|
|
return sigar_ether_ntoa(addr_str, &address->addr.mac[0]);
|
2006-07-05 00:35:27 +08:00
|
|
|
default:
|
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-11 04:42:16 +08:00
|
|
|
SIGAR_DECLARE(sigar_uint32_t) sigar_net_address_hash(sigar_net_address_t *address)
|
|
|
|
{
|
|
|
|
sigar_uint32_t hash = 0;
|
|
|
|
unsigned char *data;
|
|
|
|
int i=0, size, elts;
|
|
|
|
|
|
|
|
switch (address->family) {
|
|
|
|
case SIGAR_AF_UNSPEC:
|
|
|
|
case SIGAR_AF_INET:
|
|
|
|
return address->addr.in;
|
|
|
|
case SIGAR_AF_INET6:
|
|
|
|
data = (unsigned char *)&address->addr.in6;
|
|
|
|
size = sizeof(address->addr.in6);
|
|
|
|
elts = 4;
|
|
|
|
break;
|
|
|
|
case SIGAR_AF_LINK:
|
|
|
|
data = (unsigned char *)&address->addr.mac;
|
|
|
|
size = sizeof(address->addr.mac);
|
|
|
|
elts = 2;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (i<size) {
|
|
|
|
int j=0;
|
|
|
|
int component=0;
|
|
|
|
while (j<elts && i<size) {
|
|
|
|
component = (component << 8) + data[i];
|
|
|
|
j++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
hash += component;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
|
2007-03-13 11:49:08 +08:00
|
|
|
SIGAR_DECLARE(int)
|
|
|
|
sigar_net_interface_config_primary_get(sigar_t *sigar,
|
|
|
|
sigar_net_interface_config_t *ifconfig)
|
2004-06-22 06:37:04 +08:00
|
|
|
{
|
2007-03-13 11:49:08 +08:00
|
|
|
int i, status, found=0;
|
2004-06-22 06:37:04 +08:00
|
|
|
sigar_net_interface_list_t iflist;
|
|
|
|
|
|
|
|
if ((status = sigar_net_interface_list_get(sigar, &iflist)) != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=0; i<iflist.number; i++) {
|
|
|
|
status = sigar_net_interface_config_get(sigar,
|
2007-03-13 11:49:08 +08:00
|
|
|
iflist.data[i], ifconfig);
|
2004-06-22 06:37:04 +08:00
|
|
|
|
|
|
|
if ((status != SIGAR_OK) ||
|
2007-03-13 11:49:08 +08:00
|
|
|
(ifconfig->flags & SIGAR_IFF_LOOPBACK) ||
|
|
|
|
!ifconfig->address.addr.in || /* no ip address */
|
|
|
|
!ifconfig->hwaddr.addr.in || /* no mac address */
|
2006-12-03 04:24:52 +08:00
|
|
|
strchr(iflist.data[i], ':')) /* alias */
|
2004-06-22 06:37:04 +08:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2007-03-13 11:49:08 +08:00
|
|
|
found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sigar_net_interface_list_destroy(sigar, &iflist);
|
|
|
|
|
|
|
|
if (found) {
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
else {
|
2007-04-05 23:50:23 +08:00
|
|
|
return SIGAR_ENOENT;
|
2007-03-13 11:49:08 +08:00
|
|
|
}
|
|
|
|
}
|
2004-06-22 06:37:04 +08:00
|
|
|
|
2007-03-13 11:49:08 +08:00
|
|
|
static int fqdn_ip_get(sigar_t *sigar, char *name)
|
|
|
|
{
|
|
|
|
sigar_net_interface_config_t ifconfig;
|
|
|
|
int status;
|
2004-07-17 04:06:02 +08:00
|
|
|
|
2007-03-13 11:49:08 +08:00
|
|
|
status = sigar_net_interface_config_primary_get(sigar, &ifconfig);
|
2004-07-17 04:06:02 +08:00
|
|
|
|
2007-03-13 11:49:08 +08:00
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
|
2007-03-13 11:49:08 +08:00
|
|
|
sigar_net_address_to_string(sigar, &ifconfig.address, name);
|
|
|
|
|
|
|
|
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
|
|
|
|
"[fqdn] using ip address '%s' for fqdn",
|
|
|
|
name);
|
2004-06-22 06:37:04 +08:00
|
|
|
|
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
2006-03-03 06:53:09 +08:00
|
|
|
struct hostent *sigar_gethostbyname(const char *name,
|
|
|
|
sigar_hostent_t *data)
|
2006-02-23 13:02:11 +08:00
|
|
|
{
|
2006-03-03 06:53:09 +08:00
|
|
|
struct hostent *hp = NULL;
|
2006-02-23 13:15:10 +08:00
|
|
|
|
2006-02-23 13:02:11 +08:00
|
|
|
#if defined(__linux__)
|
2006-03-03 06:53:09 +08:00
|
|
|
gethostbyname_r(name, &data->hs,
|
|
|
|
data->buffer, sizeof(data->buffer),
|
|
|
|
&hp, &data->error);
|
2006-02-23 13:08:33 +08:00
|
|
|
#elif defined(__sun)
|
2006-03-03 06:53:09 +08:00
|
|
|
hp = gethostbyname_r(name, &data->hs,
|
|
|
|
data->buffer, sizeof(data->buffer),
|
|
|
|
&data->error);
|
|
|
|
#elif defined(SIGAR_HAS_HOSTENT_DATA)
|
|
|
|
if (gethostbyname_r(name, &data->hs, &data->hd) == 0) {
|
|
|
|
hp = &data->hs;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
data->error = h_errno;
|
|
|
|
}
|
2006-02-23 13:02:11 +08:00
|
|
|
#else
|
|
|
|
hp = gethostbyname(name);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return hp;
|
|
|
|
}
|
|
|
|
|
2006-03-03 09:33:07 +08:00
|
|
|
static struct hostent *sigar_gethostbyaddr(const char *addr,
|
|
|
|
int len, int type,
|
|
|
|
sigar_hostent_t *data)
|
|
|
|
{
|
|
|
|
struct hostent *hp = NULL;
|
|
|
|
|
|
|
|
#if defined(__linux__)
|
|
|
|
gethostbyaddr_r(addr, len, type,
|
|
|
|
&data->hs,
|
|
|
|
data->buffer, sizeof(data->buffer),
|
|
|
|
&hp, &data->error);
|
|
|
|
#elif defined(__sun)
|
|
|
|
hp = gethostbyaddr_r(addr, len, type,
|
|
|
|
&data->hs,
|
|
|
|
data->buffer, sizeof(data->buffer),
|
|
|
|
&data->error);
|
|
|
|
#elif defined(SIGAR_HAS_HOSTENT_DATA)
|
|
|
|
if (gethostbyaddr_r((char *)addr, len, type,
|
|
|
|
&data->hs, &data->hd) == 0)
|
|
|
|
{
|
|
|
|
hp = &data->hs;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
data->error = h_errno;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (!(hp = gethostbyaddr(addr, len, type))) {
|
|
|
|
data->error = h_errno;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return hp;
|
|
|
|
}
|
2004-07-17 03:10:08 +08:00
|
|
|
#define IS_FQDN(name) \
|
2005-11-09 03:15:41 +08:00
|
|
|
(name && strchr(name, '.'))
|
2004-07-17 03:10:08 +08:00
|
|
|
|
2006-09-22 06:23:48 +08:00
|
|
|
#define IS_FQDN_MATCH(lookup, name) \
|
|
|
|
(IS_FQDN(lookup) && strnEQ(lookup, name, strlen(name)))
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
#define FQDN_SET(fqdn) \
|
|
|
|
SIGAR_STRNCPY(name, fqdn, namelen)
|
|
|
|
|
|
|
|
SIGAR_DECLARE(int) sigar_fqdn_get(sigar_t *sigar, char *name, int namelen)
|
|
|
|
{
|
2006-09-22 06:23:48 +08:00
|
|
|
register int is_debug = SIGAR_LOG_IS_DEBUG(sigar);
|
2006-03-03 09:12:41 +08:00
|
|
|
sigar_hostent_t data;
|
2004-06-22 06:37:04 +08:00
|
|
|
struct hostent *p;
|
|
|
|
char domain[SIGAR_FQDN_LEN + 1];
|
|
|
|
#ifdef WIN32
|
|
|
|
int status = sigar_wsa_init(sigar);
|
|
|
|
|
|
|
|
if (status != SIGAR_OK) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (gethostname(name, namelen - 1) != 0) {
|
2004-07-06 09:00:14 +08:00
|
|
|
sigar_log_printf(sigar, SIGAR_LOG_ERROR,
|
2004-07-17 04:06:02 +08:00
|
|
|
"[fqdn] gethostname failed: %s",
|
|
|
|
sigar_strerror(sigar, errno));
|
2004-07-06 09:00:14 +08:00
|
|
|
return errno;
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
2004-07-17 04:06:02 +08:00
|
|
|
else {
|
2006-09-22 06:23:48 +08:00
|
|
|
if (is_debug) {
|
2004-07-17 04:06:02 +08:00
|
|
|
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
|
2006-09-22 06:42:53 +08:00
|
|
|
"[fqdn] gethostname()=='%s'",
|
2004-07-17 04:06:02 +08:00
|
|
|
name);
|
|
|
|
}
|
|
|
|
}
|
2004-06-22 06:37:04 +08:00
|
|
|
|
2006-03-03 09:12:41 +08:00
|
|
|
if (!(p = sigar_gethostbyname(name, &data))) {
|
2006-09-22 06:23:48 +08:00
|
|
|
if (is_debug) {
|
2004-07-06 09:00:14 +08:00
|
|
|
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
|
2004-07-17 04:06:02 +08:00
|
|
|
"[fqdn] gethostbyname(%s) failed: %s",
|
|
|
|
name, sigar_strerror(sigar, errno));
|
2004-07-06 09:00:14 +08:00
|
|
|
}
|
|
|
|
|
2004-07-17 03:10:08 +08:00
|
|
|
if (!IS_FQDN(name)) {
|
2004-06-22 06:37:04 +08:00
|
|
|
fqdn_ip_get(sigar, name);
|
|
|
|
}
|
2004-07-06 09:00:14 +08:00
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
2006-09-22 06:23:48 +08:00
|
|
|
if (IS_FQDN_MATCH(p->h_name, name)) {
|
2004-06-22 06:37:04 +08:00
|
|
|
FQDN_SET(p->h_name);
|
2004-07-06 11:01:50 +08:00
|
|
|
|
2004-07-06 09:00:14 +08:00
|
|
|
sigar_log(sigar, SIGAR_LOG_DEBUG,
|
2004-07-17 04:06:02 +08:00
|
|
|
"[fqdn] resolved using gethostbyname.h_name");
|
2004-07-06 11:01:50 +08:00
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
2004-07-17 04:06:02 +08:00
|
|
|
else {
|
|
|
|
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
|
|
|
|
"[fqdn] unresolved using gethostbyname.h_name");
|
|
|
|
}
|
2004-06-22 06:37:04 +08:00
|
|
|
|
|
|
|
if (p->h_aliases) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i=0; p->h_aliases[i]; i++) {
|
2006-09-22 06:42:53 +08:00
|
|
|
if (IS_FQDN_MATCH(p->h_aliases[i], name)) {
|
2004-06-22 06:37:04 +08:00
|
|
|
FQDN_SET(p->h_aliases[i]);
|
2004-07-06 09:00:14 +08:00
|
|
|
|
|
|
|
sigar_log(sigar, SIGAR_LOG_DEBUG,
|
2004-07-17 04:06:02 +08:00
|
|
|
"[fqdn] resolved using gethostbyname.h_aliases");
|
2004-07-06 09:00:14 +08:00
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
2006-09-22 06:42:53 +08:00
|
|
|
else if (is_debug) {
|
|
|
|
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
|
|
|
|
"[fqdn] gethostbyname(%s).alias[%d]=='%s'",
|
|
|
|
name, i, p->h_aliases[i]);
|
|
|
|
}
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-07-17 04:06:02 +08:00
|
|
|
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
|
|
|
|
"[fqdn] unresolved using gethostbyname.h_aliases");
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
if (p->h_addr_list) {
|
|
|
|
int i,j;
|
|
|
|
|
|
|
|
for (i=0; p->h_addr_list[i]; i++) {
|
2006-10-20 04:10:13 +08:00
|
|
|
char addr[SIGAR_INET6_ADDRSTRLEN];
|
2006-09-22 06:23:48 +08:00
|
|
|
struct in_addr *in =
|
|
|
|
(struct in_addr *)p->h_addr_list[i];
|
|
|
|
|
2006-03-03 06:53:09 +08:00
|
|
|
struct hostent *q =
|
2006-03-03 09:33:07 +08:00
|
|
|
sigar_gethostbyaddr(p->h_addr_list[i],
|
|
|
|
p->h_length,
|
|
|
|
p->h_addrtype,
|
|
|
|
&data);
|
2005-11-09 03:15:41 +08:00
|
|
|
|
2006-09-22 06:23:48 +08:00
|
|
|
if (is_debug) {
|
|
|
|
sigar_inet_ntoa(sigar, in->s_addr, addr);
|
|
|
|
}
|
2005-11-09 03:15:41 +08:00
|
|
|
|
2006-09-22 06:23:48 +08:00
|
|
|
if (!q) {
|
|
|
|
if (is_debug) {
|
2005-11-09 03:15:41 +08:00
|
|
|
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
|
|
|
|
"[fqdn] gethostbyaddr(%s) failed: %s",
|
|
|
|
addr,
|
|
|
|
sigar_strerror(sigar, errno));
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2006-09-22 06:23:48 +08:00
|
|
|
if (IS_FQDN_MATCH(q->h_name, name)) {
|
2004-06-22 06:37:04 +08:00
|
|
|
FQDN_SET(q->h_name);
|
2004-07-06 09:00:14 +08:00
|
|
|
|
|
|
|
sigar_log(sigar, SIGAR_LOG_DEBUG,
|
2004-07-17 04:06:02 +08:00
|
|
|
"[fqdn] resolved using gethostbyaddr.h_name");
|
2004-07-06 09:00:14 +08:00
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
else {
|
2006-09-22 06:42:53 +08:00
|
|
|
if (is_debug) {
|
|
|
|
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
|
|
|
|
"[fqdn] gethostbyaddr(%s)=='%s'",
|
|
|
|
addr, q->h_name);
|
|
|
|
}
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
for (j=0; q->h_aliases[j]; j++) {
|
2006-09-22 06:42:53 +08:00
|
|
|
if (IS_FQDN_MATCH(q->h_aliases[j], name)) {
|
2004-06-22 06:37:04 +08:00
|
|
|
FQDN_SET(q->h_aliases[j]);
|
2004-07-06 09:00:14 +08:00
|
|
|
|
|
|
|
sigar_log(sigar, SIGAR_LOG_DEBUG,
|
2004-07-17 04:06:02 +08:00
|
|
|
"[fqdn] resolved using "
|
2004-07-06 09:00:14 +08:00
|
|
|
"gethostbyaddr.h_aliases");
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
2006-09-22 06:23:48 +08:00
|
|
|
else if (is_debug) {
|
|
|
|
sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
|
2006-09-22 06:42:53 +08:00
|
|
|
"[fqdn] gethostbyaddr(%s).alias[%d]=='%s'",
|
2006-09-22 06:23:48 +08:00
|
|
|
addr, j, q->h_aliases[j]);
|
|
|
|
}
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-04 00:26:56 +08:00
|
|
|
sigar_log(sigar, SIGAR_LOG_DEBUG,
|
|
|
|
"[fqdn] unresolved using gethostbyname.h_addr_list");
|
2004-07-17 04:06:02 +08:00
|
|
|
|
2005-08-28 13:59:53 +08:00
|
|
|
#if !defined(WIN32) && !defined(NETWARE)
|
2004-07-17 03:10:08 +08:00
|
|
|
if (!IS_FQDN(name) && /* e.g. aix gethostname is already fqdn */
|
2004-06-22 06:37:04 +08:00
|
|
|
(getdomainname(domain, sizeof(domain) - 1) == 0) &&
|
|
|
|
(domain[0] != '\0') &&
|
|
|
|
(domain[0] != '(')) /* linux default is "(none)" */
|
|
|
|
{
|
|
|
|
/* sprintf(name, "%s.%s", name, domain); */
|
|
|
|
char *ptr = name;
|
|
|
|
int len = strlen(name);
|
|
|
|
ptr += len;
|
|
|
|
*ptr++ = '.';
|
|
|
|
namelen -= (len+1);
|
|
|
|
SIGAR_STRNCPY(ptr, domain, namelen);
|
2004-07-06 09:00:14 +08:00
|
|
|
|
|
|
|
sigar_log(sigar, SIGAR_LOG_DEBUG,
|
2004-07-17 04:06:02 +08:00
|
|
|
"[fqdn] resolved using getdomainname");
|
2004-06-22 06:37:04 +08:00
|
|
|
}
|
2004-07-06 11:01:50 +08:00
|
|
|
else {
|
|
|
|
sigar_log(sigar, SIGAR_LOG_DEBUG,
|
2004-07-17 04:06:02 +08:00
|
|
|
"[fqdn] getdomainname failed");
|
2004-07-06 11:01:50 +08:00
|
|
|
}
|
2004-06-22 06:37:04 +08:00
|
|
|
#endif
|
|
|
|
|
2004-07-17 04:06:02 +08:00
|
|
|
if (!IS_FQDN(name)) {
|
|
|
|
fqdn_ip_get(sigar, name);
|
|
|
|
}
|
|
|
|
|
2004-06-22 06:37:04 +08:00
|
|
|
return SIGAR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef MAX_STRING_LEN
|
|
|
|
#define MAX_STRING_LEN 8192
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
/* The windows version of getPasswordNative was lifted from apr */
|
|
|
|
SIGAR_DECLARE(char *) sigar_password_get(const char *prompt)
|
|
|
|
{
|
|
|
|
static char password[MAX_STRING_LEN];
|
|
|
|
int n = 0;
|
|
|
|
int ch;
|
|
|
|
|
|
|
|
fputs(prompt, stderr);
|
|
|
|
fflush(stderr);
|
|
|
|
|
|
|
|
while ((ch = _getch()) != '\r') {
|
|
|
|
if (ch == EOF) /* EOF */ {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else if (ch == 0 || ch == 0xE0) {
|
|
|
|
/* FN Keys (0 or E0) are a sentinal for a FN code */
|
|
|
|
ch = (ch << 4) | _getch();
|
|
|
|
/* Catch {DELETE}, {<--}, Num{DEL} and Num{<--} */
|
|
|
|
if ((ch == 0xE53 || ch == 0xE4B || ch == 0x053 || ch == 0x04b) && n) {
|
|
|
|
password[--n] = '\0';
|
|
|
|
fputs("\b \b", stderr);
|
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fputc('\a', stderr);
|
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((ch == '\b' || ch == 127) && n) /* BS/DEL */ {
|
|
|
|
password[--n] = '\0';
|
|
|
|
fputs("\b \b", stderr);
|
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
else if (ch == 3) /* CTRL+C */ {
|
|
|
|
/* _getch() bypasses Ctrl+C but not Ctrl+Break detection! */
|
|
|
|
fputs("^C\n", stderr);
|
|
|
|
fflush(stderr);
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
else if (ch == 26) /* CTRL+Z */ {
|
|
|
|
fputs("^Z\n", stderr);
|
|
|
|
fflush(stderr);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else if (ch == 27) /* ESC */ {
|
|
|
|
fputc('\n', stderr);
|
|
|
|
fputs(prompt, stderr);
|
|
|
|
fflush(stderr);
|
|
|
|
n = 0;
|
|
|
|
}
|
|
|
|
else if ((n < sizeof(password) - 1) && !iscntrl(ch)) {
|
|
|
|
password[n++] = ch;
|
|
|
|
fputc(' ', stderr);
|
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fputc('\a', stderr);
|
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fputc('\n', stderr);
|
|
|
|
fflush(stderr);
|
|
|
|
password[n] = '\0';
|
|
|
|
|
|
|
|
return password;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
/* linux/hpux/solaris getpass() prototype lives here */
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include <termios.h>
|
|
|
|
|
|
|
|
/* from apr_getpass.c */
|
|
|
|
|
|
|
|
#if defined(SIGAR_HPUX)
|
|
|
|
# define getpass termios_getpass
|
|
|
|
#elif defined(SIGAR_SOLARIS)
|
|
|
|
# define getpass getpassphrase
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef SIGAR_HPUX
|
|
|
|
static char *termios_getpass(const char *prompt)
|
|
|
|
{
|
|
|
|
struct termios attr;
|
|
|
|
static char password[MAX_STRING_LEN];
|
|
|
|
unsigned int n=0;
|
|
|
|
|
|
|
|
fputs(prompt, stderr);
|
|
|
|
fflush(stderr);
|
|
|
|
|
|
|
|
if (tcgetattr(STDIN_FILENO, &attr) != 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
attr.c_lflag &= ~(ECHO);
|
|
|
|
|
|
|
|
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &attr) != 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((password[n] = getchar()) != '\n') {
|
|
|
|
if (n < (sizeof(password) - 1) &&
|
|
|
|
(password[n] >= ' ') &&
|
|
|
|
(password[n] <= '~'))
|
|
|
|
{
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
fputs(prompt, stderr);
|
|
|
|
fflush(stderr);
|
|
|
|
n = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
password[n] = '\0';
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
if (n > (MAX_STRING_LEN - 1)) {
|
|
|
|
password[MAX_STRING_LEN - 1] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
attr.c_lflag |= ECHO;
|
|
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &attr);
|
|
|
|
|
|
|
|
return (char *)&password;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
SIGAR_DECLARE(char *) sigar_password_get(const char *prompt)
|
|
|
|
{
|
|
|
|
char *buf = NULL;
|
|
|
|
|
|
|
|
/* the linux version of getpass prints the prompt to the tty; ok.
|
|
|
|
* the solaris version prints the prompt to stderr; not ok.
|
|
|
|
* so print the prompt to /dev/tty ourselves if possible (always should be)
|
|
|
|
*/
|
|
|
|
|
|
|
|
FILE *tty = NULL;
|
|
|
|
|
|
|
|
if ((tty = fopen("/dev/tty", "w"))) {
|
|
|
|
fprintf(tty, "%s", prompt);
|
|
|
|
fflush(tty);
|
|
|
|
|
|
|
|
buf = getpass(tty ? "" : prompt);
|
|
|
|
fclose(tty);
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* WIN32 */
|