1/* 2 * Copyright (c) 2004-2009 Hyperic, Inc. 3 * Copyright (c) 2009 SpringSource, Inc. 4 * Copyright (c) 2009-2010 VMware, Inc. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19#include <errno.h> 20#include <stdio.h> 21 22#ifndef WIN32 23#include <sys/types.h> 24#include <sys/socket.h> 25#include <sys/time.h> 26#endif 27#if defined(__OpenBSD__) || defined(__FreeBSD__) 28#include <netinet/in.h> 29#endif 30#ifndef WIN32 31#include <arpa/inet.h> 32#endif 33 34#include "sigar.h" 35#include "sigar_private.h" 36#include "sigar_util.h" 37#include "sigar_os.h" 38#include "sigar_format.h" 39 40SIGAR_DECLARE(int) sigar_open(sigar_t **sigar) 41{ 42 int status = sigar_os_open(sigar); 43 44 if (status == SIGAR_OK) { 45 /* use env to revert to old behavior */ 46 (*sigar)->cpu_list_cores = getenv("SIGAR_CPU_LIST_SOCKETS") ? 0 : 1; 47 (*sigar)->pid = 0; 48 (*sigar)->ifconf_buf = NULL; 49 (*sigar)->ifconf_len = 0; 50 (*sigar)->log_level = -1; /* log nothing by default */ 51 (*sigar)->log_impl = NULL; 52 (*sigar)->log_data = NULL; 53 (*sigar)->ptql_re_impl = NULL; 54 (*sigar)->ptql_re_data = NULL; 55 (*sigar)->self_path = NULL; 56 (*sigar)->fsdev = NULL; 57 (*sigar)->pids = NULL; 58 (*sigar)->proc_cpu = NULL; 59 (*sigar)->net_listen = NULL; 60 (*sigar)->net_services_tcp = NULL; 61 (*sigar)->net_services_udp = NULL; 62 } 63 64 return status; 65} 66 67SIGAR_DECLARE(int) sigar_close(sigar_t *sigar) 68{ 69 if (sigar->ifconf_buf) { 70 free(sigar->ifconf_buf); 71 } 72 if (sigar->self_path) { 73 free(sigar->self_path); 74 } 75 if (sigar->pids) { 76 sigar_proc_list_destroy(sigar, sigar->pids); 77 free(sigar->pids); 78 } 79 if (sigar->fsdev) { 80 sigar_cache_destroy(sigar->fsdev); 81 } 82 if (sigar->proc_cpu) { 83 sigar_cache_destroy(sigar->proc_cpu); 84 } 85 if (sigar->net_listen) { 86 sigar_cache_destroy(sigar->net_listen); 87 } 88 if (sigar->net_services_tcp) { 89 sigar_cache_destroy(sigar->net_services_tcp); 90 } 91 if (sigar->net_services_udp) { 92 sigar_cache_destroy(sigar->net_services_udp); 93 } 94 95 return sigar_os_close(sigar); 96} 97 98#ifndef __linux__ /* linux has a special case */ 99SIGAR_DECLARE(sigar_pid_t) sigar_pid_get(sigar_t *sigar) 100{ 101 if (!sigar->pid) { 102 sigar->pid = getpid(); 103 } 104 105 return sigar->pid; 106} 107#endif 108 109/* XXX: add clear() function */ 110/* XXX: check for stale-ness using start_time */ 111SIGAR_DECLARE(int) sigar_proc_cpu_get(sigar_t *sigar, sigar_pid_t pid, 112 sigar_proc_cpu_t *proccpu) 113{ 114 sigar_cache_entry_t *entry; 115 sigar_proc_cpu_t *prev; 116 sigar_uint64_t otime, time_now = sigar_time_now_millis(); 117 sigar_uint64_t time_diff, total_diff; 118 int status; 119 120 if (!sigar->proc_cpu) { 121 sigar->proc_cpu = sigar_cache_new(128); 122 } 123 124 entry = sigar_cache_get(sigar->proc_cpu, pid); 125 if (entry->value) { 126 prev = (sigar_proc_cpu_t *)entry->value; 127 } 128 else { 129 prev = entry->value = malloc(sizeof(*prev)); 130 SIGAR_ZERO(prev); 131 } 132 133 time_diff = time_now - prev->last_time; 134 proccpu->last_time = prev->last_time = time_now; 135 136 if (time_diff == 0) { 137 /* we were just called within < 1 second ago. */ 138 memcpy(proccpu, prev, sizeof(*proccpu)); 139 return SIGAR_OK; 140 } 141 142 otime = prev->total; 143 144 status = 145 sigar_proc_time_get(sigar, pid, 146 (sigar_proc_time_t *)proccpu); 147 148 if (status != SIGAR_OK) { 149 return status; 150 } 151 152 memcpy(prev, proccpu, sizeof(*prev)); 153 154 if (proccpu->total < otime) { 155 /* XXX this should not happen */ 156 otime = 0; 157 } 158 159 if (otime == 0) { 160 proccpu->percent = 0.0; 161 /* first time called */ 162 return SIGAR_OK; 163 } 164 165 total_diff = proccpu->total - otime; 166 proccpu->percent = total_diff / (double)time_diff; 167 168 return SIGAR_OK; 169} 170 171SIGAR_DECLARE(int) sigar_proc_stat_get(sigar_t *sigar, 172 sigar_proc_stat_t *procstat) 173{ 174 int status, i; 175 sigar_proc_list_t *pids; 176 177 SIGAR_ZERO(procstat); 178 procstat->threads = SIGAR_FIELD_NOTIMPL; 179 180 if ((status = sigar_proc_list_get(sigar, NULL)) != SIGAR_OK) { 181 return status; 182 } 183 184 pids = sigar->pids; 185 procstat->total = pids->number; 186 187 for (i=0; i<pids->number; i++) { 188 sigar_proc_state_t state; 189 190 status = sigar_proc_state_get(sigar, pids->data[i], &state); 191 if (status != SIGAR_OK) { 192 continue; 193 } 194 195 if (state.threads != SIGAR_FIELD_NOTIMPL) { 196 procstat->threads += state.threads; 197 } 198 199 switch (state.state) { 200 case SIGAR_PROC_STATE_IDLE: 201 procstat->idle++; 202 break; 203 case SIGAR_PROC_STATE_RUN: 204 procstat->running++; 205 break; 206 case SIGAR_PROC_STATE_SLEEP: 207 procstat->sleeping++; 208 break; 209 case SIGAR_PROC_STATE_STOP: 210 procstat->stopped++; 211 break; 212 case SIGAR_PROC_STATE_ZOMBIE: 213 procstat->zombie++; 214 break; 215 default: 216 break; 217 } 218 } 219 220 return SIGAR_OK; 221} 222 223SIGAR_DECLARE(int) sigar_sys_info_get(sigar_t *sigar, 224 sigar_sys_info_t *sysinfo) 225{ 226 SIGAR_ZERO(sysinfo); 227 228#ifndef WIN32 229 sigar_sys_info_get_uname(sysinfo); 230#endif 231 232 sigar_os_sys_info_get(sigar, sysinfo); 233 234 return SIGAR_OK; 235} 236 237#ifndef WIN32 238 239#include <sys/utsname.h> 240 241int sigar_sys_info_get_uname(sigar_sys_info_t *sysinfo) 242{ 243 struct utsname name; 244 245 uname(&name); 246 247 SIGAR_SSTRCPY(sysinfo->version, name.release); 248 SIGAR_SSTRCPY(sysinfo->vendor_name, name.sysname); 249 SIGAR_SSTRCPY(sysinfo->name, name.sysname); 250 SIGAR_SSTRCPY(sysinfo->machine, name.machine); 251 SIGAR_SSTRCPY(sysinfo->arch, name.machine); 252 SIGAR_SSTRCPY(sysinfo->patch_level, "unknown"); 253 254 return SIGAR_OK; 255} 256 257SIGAR_DECLARE(int) 258sigar_proc_cred_name_get(sigar_t *sigar, sigar_pid_t pid, 259 sigar_proc_cred_name_t *proccredname) 260{ 261 sigar_proc_cred_t cred; 262 263 int status = sigar_proc_cred_get(sigar, pid, &cred); 264 265 if (status != SIGAR_OK) { 266 return status; 267 } 268 269 status = sigar_user_name_get(sigar, cred.uid, 270 proccredname->user, 271 sizeof(proccredname->user)); 272 273 if (status != SIGAR_OK) { 274 return status; 275 } 276 277 status = sigar_group_name_get(sigar, cred.gid, 278 proccredname->group, 279 sizeof(proccredname->group)); 280 281 return status; 282} 283 284#endif /* WIN32 */ 285 286int sigar_proc_list_create(sigar_proc_list_t *proclist) 287{ 288 proclist->number = 0; 289 proclist->size = SIGAR_PROC_LIST_MAX; 290 proclist->data = malloc(sizeof(*(proclist->data)) * 291 proclist->size); 292 return SIGAR_OK; 293} 294 295int sigar_proc_list_grow(sigar_proc_list_t *proclist) 296{ 297 proclist->data = realloc(proclist->data, 298 sizeof(*(proclist->data)) * 299 (proclist->size + SIGAR_PROC_LIST_MAX)); 300 proclist->size += SIGAR_PROC_LIST_MAX; 301 302 return SIGAR_OK; 303} 304 305SIGAR_DECLARE(int) sigar_proc_list_destroy(sigar_t *sigar, 306 sigar_proc_list_t *proclist) 307{ 308 if (proclist->size) { 309 free(proclist->data); 310 proclist->number = proclist->size = 0; 311 } 312 313 return SIGAR_OK; 314} 315 316SIGAR_DECLARE(int) sigar_proc_list_get(sigar_t *sigar, 317 sigar_proc_list_t *proclist) 318{ 319 if (proclist == NULL) { 320 /* internal re-use */ 321 if (sigar->pids == NULL) { 322 sigar->pids = malloc(sizeof(*sigar->pids)); 323 sigar_proc_list_create(sigar->pids); 324 } 325 else { 326 sigar->pids->number = 0; 327 } 328 proclist = sigar->pids; 329 } 330 else { 331 sigar_proc_list_create(proclist); 332 } 333 334 return sigar_os_proc_list_get(sigar, proclist); 335} 336 337int sigar_proc_args_create(sigar_proc_args_t *procargs) 338{ 339 procargs->number = 0; 340 procargs->size = SIGAR_PROC_ARGS_MAX; 341 procargs->data = malloc(sizeof(*(procargs->data)) * 342 procargs->size); 343 return SIGAR_OK; 344} 345 346int sigar_proc_args_grow(sigar_proc_args_t *procargs) 347{ 348 procargs->data = realloc(procargs->data, 349 sizeof(*(procargs->data)) * 350 (procargs->size + SIGAR_PROC_ARGS_MAX)); 351 procargs->size += SIGAR_PROC_ARGS_MAX; 352 353 return SIGAR_OK; 354} 355 356SIGAR_DECLARE(int) sigar_proc_args_destroy(sigar_t *sigar, 357 sigar_proc_args_t *procargs) 358{ 359 unsigned int i; 360 361 if (procargs->size) { 362 for (i=0; i<procargs->number; i++) { 363 free(procargs->data[i]); 364 } 365 free(procargs->data); 366 procargs->number = procargs->size = 0; 367 } 368 369 return SIGAR_OK; 370} 371 372SIGAR_DECLARE(int) sigar_proc_args_get(sigar_t *sigar, 373 sigar_pid_t pid, 374 sigar_proc_args_t *procargs) 375{ 376 int status; 377 sigar_proc_args_create(procargs); 378 status = sigar_os_proc_args_get(sigar, pid, procargs); 379 if (status != SIGAR_OK) { 380 sigar_proc_args_destroy(sigar, procargs); 381 } 382 return status; 383} 384 385int sigar_file_system_list_create(sigar_file_system_list_t *fslist) 386{ 387 fslist->number = 0; 388 fslist->size = SIGAR_FS_MAX; 389 fslist->data = malloc(sizeof(*(fslist->data)) * 390 fslist->size); 391 return SIGAR_OK; 392} 393 394int sigar_file_system_list_grow(sigar_file_system_list_t *fslist) 395{ 396 fslist->data = realloc(fslist->data, 397 sizeof(*(fslist->data)) * 398 (fslist->size + SIGAR_FS_MAX)); 399 fslist->size += SIGAR_FS_MAX; 400 401 return SIGAR_OK; 402} 403 404/* indexed with sigar_file_system_type_e */ 405static const char *fstype_names[] = { 406 "unknown", "none", "local", "remote", "ram", "cdrom", "swap" 407}; 408 409static int sigar_common_fs_type_get(sigar_file_system_t *fsp) 410{ 411 char *type = fsp->sys_type_name; 412 413 switch (*type) { 414 case 'n': 415 if (strnEQ(type, "nfs", 3)) { 416 fsp->type = SIGAR_FSTYPE_NETWORK; 417 } 418 break; 419 case 's': 420 if (strEQ(type, "smbfs")) { /* samba */ 421 fsp->type = SIGAR_FSTYPE_NETWORK; 422 } 423 else if (strEQ(type, "swap")) { 424 fsp->type = SIGAR_FSTYPE_SWAP; 425 } 426 break; 427 case 'a': 428 if (strEQ(type, "afs")) { 429 fsp->type = SIGAR_FSTYPE_NETWORK; 430 } 431 break; 432 case 'i': 433 if (strEQ(type, "iso9660")) { 434 fsp->type = SIGAR_FSTYPE_CDROM; 435 } 436 break; 437 case 'c': 438 if (strEQ(type, "cvfs")) { 439 fsp->type = SIGAR_FSTYPE_LOCAL_DISK; 440 } 441 else if (strEQ(type, "cifs")) { 442 fsp->type = SIGAR_FSTYPE_NETWORK; 443 } 444 break; 445 case 'm': 446 if (strEQ(type, "msdos") || strEQ(type, "minix")) { 447 fsp->type = SIGAR_FSTYPE_LOCAL_DISK; 448 } 449 break; 450 case 'h': 451 if (strEQ(type, "hpfs")) { 452 fsp->type = SIGAR_FSTYPE_LOCAL_DISK; 453 } 454 break; 455 case 'v': 456 if (strEQ(type, "vxfs")) { 457 fsp->type = SIGAR_FSTYPE_LOCAL_DISK; 458 } 459 else if (strEQ(type, "vfat")) { 460 fsp->type = SIGAR_FSTYPE_LOCAL_DISK; 461 } 462 break; 463 case 'z': 464 if (strEQ(type, "zfs")) { 465 fsp->type = SIGAR_FSTYPE_LOCAL_DISK; 466 } 467 break; 468 } 469 470 return fsp->type; 471} 472 473void sigar_fs_type_get(sigar_file_system_t *fsp) 474{ 475 if (!(fsp->type || /* already set */ 476 sigar_os_fs_type_get(fsp) || /* try os specifics first */ 477 sigar_common_fs_type_get(fsp))) /* try common ones last */ 478 { 479 fsp->type = SIGAR_FSTYPE_NONE; 480 } 481 482 if (fsp->type >= SIGAR_FSTYPE_MAX) { 483 fsp->type = SIGAR_FSTYPE_NONE; 484 } 485 486 strcpy(fsp->type_name, fstype_names[fsp->type]); 487} 488 489 490SIGAR_DECLARE(int) 491sigar_file_system_list_destroy(sigar_t *sigar, 492 sigar_file_system_list_t *fslist) 493{ 494 if (fslist->size) { 495 free(fslist->data); 496 fslist->number = fslist->size = 0; 497 } 498 499 return SIGAR_OK; 500} 501 502#ifndef NFS_PROGRAM 503#define NFS_PROGRAM 100003 504#endif 505 506#ifndef NFS_VERSION 507#define NFS_VERSION 2 508#endif 509 510SIGAR_DECLARE(int) 511sigar_file_system_ping(sigar_t *sigar, 512 sigar_file_system_t *fs) 513{ 514 int status = SIGAR_OK; 515#ifndef WIN32 516 char *ptr; 517 518 if ((fs->type == SIGAR_FSTYPE_NETWORK) && 519 strEQ(fs->sys_type_name, "nfs") && 520 (ptr = strchr(fs->dev_name, ':'))) 521 { 522 *ptr = '\0'; /* "hostname:/mount" -> "hostname" */ 523 524 status = sigar_rpc_ping(fs->dev_name, 525 SIGAR_NETCONN_UDP, 526 NFS_PROGRAM, NFS_VERSION); 527 528 if (SIGAR_LOG_IS_DEBUG(sigar)) { 529 sigar_log_printf(sigar, SIGAR_LOG_DEBUG, 530 "[fs_ping] %s -> %s: %s", 531 fs->dir_name, fs->dev_name, 532 ((status == SIGAR_OK) ? 533 "OK" : sigar_rpc_strerror(status))); 534 } 535 536 *ptr = ':'; /* "hostname" -> "hostname:/mount" */ 537 } 538#endif 539 return status; 540} 541 542int sigar_cpu_info_list_create(sigar_cpu_info_list_t *cpu_infos) 543{ 544 cpu_infos->number = 0; 545 cpu_infos->size = SIGAR_CPU_INFO_MAX; 546 cpu_infos->data = malloc(sizeof(*(cpu_infos->data)) * 547 cpu_infos->size); 548 return SIGAR_OK; 549} 550 551int sigar_cpu_info_list_grow(sigar_cpu_info_list_t *cpu_infos) 552{ 553 cpu_infos->data = realloc(cpu_infos->data, 554 sizeof(*(cpu_infos->data)) * 555 (cpu_infos->size + SIGAR_CPU_INFO_MAX)); 556 cpu_infos->size += SIGAR_CPU_INFO_MAX; 557 558 return SIGAR_OK; 559} 560 561SIGAR_DECLARE(int) 562sigar_cpu_info_list_destroy(sigar_t *sigar, 563 sigar_cpu_info_list_t *cpu_infos) 564{ 565 if (cpu_infos->size) { 566 free(cpu_infos->data); 567 cpu_infos->number = cpu_infos->size = 0; 568 } 569 570 return SIGAR_OK; 571} 572 573int sigar_cpu_list_create(sigar_cpu_list_t *cpulist) 574{ 575 cpulist->number = 0; 576 cpulist->size = SIGAR_CPU_INFO_MAX; 577 cpulist->data = malloc(sizeof(*(cpulist->data)) * 578 cpulist->size); 579 return SIGAR_OK; 580} 581 582int sigar_cpu_list_grow(sigar_cpu_list_t *cpulist) 583{ 584 cpulist->data = realloc(cpulist->data, 585 sizeof(*(cpulist->data)) * 586 (cpulist->size + SIGAR_CPU_INFO_MAX)); 587 cpulist->size += SIGAR_CPU_INFO_MAX; 588 589 return SIGAR_OK; 590} 591 592SIGAR_DECLARE(int) sigar_cpu_list_destroy(sigar_t *sigar, 593 sigar_cpu_list_t *cpulist) 594{ 595 if (cpulist->size) { 596 free(cpulist->data); 597 cpulist->number = cpulist->size = 0; 598 } 599 600 return SIGAR_OK; 601} 602 603int sigar_net_route_list_create(sigar_net_route_list_t *routelist) 604{ 605 routelist->number = 0; 606 routelist->size = SIGAR_NET_ROUTE_LIST_MAX; 607 routelist->data = malloc(sizeof(*(routelist->data)) * 608 routelist->size); 609 return SIGAR_OK; 610} 611 612int sigar_net_route_list_grow(sigar_net_route_list_t *routelist) 613{ 614 routelist->data = 615 realloc(routelist->data, 616 sizeof(*(routelist->data)) * 617 (routelist->size + SIGAR_NET_ROUTE_LIST_MAX)); 618 routelist->size += SIGAR_NET_ROUTE_LIST_MAX; 619 620 return SIGAR_OK; 621} 622 623SIGAR_DECLARE(int) sigar_net_route_list_destroy(sigar_t *sigar, 624 sigar_net_route_list_t *routelist) 625{ 626 if (routelist->size) { 627 free(routelist->data); 628 routelist->number = routelist->size = 0; 629 } 630 631 return SIGAR_OK; 632} 633 634int sigar_net_interface_list_create(sigar_net_interface_list_t *iflist) 635{ 636 iflist->number = 0; 637 iflist->size = SIGAR_NET_IFLIST_MAX; 638 iflist->data = malloc(sizeof(*(iflist->data)) * 639 iflist->size); 640 return SIGAR_OK; 641} 642 643int sigar_net_interface_list_grow(sigar_net_interface_list_t *iflist) 644{ 645 iflist->data = realloc(iflist->data, 646 sizeof(*(iflist->data)) * 647 (iflist->size + SIGAR_NET_IFLIST_MAX)); 648 iflist->size += SIGAR_NET_IFLIST_MAX; 649 650 return SIGAR_OK; 651} 652 653SIGAR_DECLARE(int) 654sigar_net_interface_list_destroy(sigar_t *sigar, 655 sigar_net_interface_list_t *iflist) 656{ 657 unsigned int i; 658 659 if (iflist->size) { 660 for (i=0; i<iflist->number; i++) { 661 free(iflist->data[i]); 662 } 663 free(iflist->data); 664 iflist->number = iflist->size = 0; 665 } 666 667 return SIGAR_OK; 668} 669 670int sigar_net_connection_list_create(sigar_net_connection_list_t *connlist) 671{ 672 connlist->number = 0; 673 connlist->size = SIGAR_NET_CONNLIST_MAX; 674 connlist->data = malloc(sizeof(*(connlist->data)) * 675 connlist->size); 676 return SIGAR_OK; 677} 678 679int sigar_net_connection_list_grow(sigar_net_connection_list_t *connlist) 680{ 681 connlist->data = 682 realloc(connlist->data, 683 sizeof(*(connlist->data)) * 684 (connlist->size + SIGAR_NET_CONNLIST_MAX)); 685 connlist->size += SIGAR_NET_CONNLIST_MAX; 686 687 return SIGAR_OK; 688} 689 690SIGAR_DECLARE(int) 691sigar_net_connection_list_destroy(sigar_t *sigar, 692 sigar_net_connection_list_t *connlist) 693{ 694 if (connlist->size) { 695 free(connlist->data); 696 connlist->number = connlist->size = 0; 697 } 698 699 return SIGAR_OK; 700} 701 702#if !defined(__linux__) 703/* 704 * implement sigar_net_connection_list_get using sigar_net_connection_walk 705 * linux has its own list_get impl. 706 */ 707static int net_connection_list_walker(sigar_net_connection_walker_t *walker, 708 sigar_net_connection_t *conn) 709{ 710 sigar_net_connection_list_t *connlist = 711 (sigar_net_connection_list_t *)walker->data; 712 713 SIGAR_NET_CONNLIST_GROW(connlist); 714 memcpy(&connlist->data[connlist->number++], 715 conn, sizeof(*conn)); 716 717 return SIGAR_OK; /* continue loop */ 718} 719 720SIGAR_DECLARE(int) 721sigar_net_connection_list_get(sigar_t *sigar, 722 sigar_net_connection_list_t *connlist, 723 int flags) 724{ 725 int status; 726 sigar_net_connection_walker_t walker; 727 728 sigar_net_connection_list_create(connlist); 729 730 walker.sigar = sigar; 731 walker.flags = flags; 732 walker.data = connlist; 733 walker.add_connection = net_connection_list_walker; 734 735 status = sigar_net_connection_walk(&walker); 736 737 if (status != SIGAR_OK) { 738 sigar_net_connection_list_destroy(sigar, connlist); 739 } 740 741 return status; 742} 743#endif 744 745static void sigar_net_listen_address_add(sigar_t *sigar, 746 sigar_net_connection_t *conn) 747{ 748 sigar_cache_entry_t *entry = 749 sigar_cache_get(sigar->net_listen, conn->local_port); 750 751 if (entry->value) { 752 if (conn->local_address.family == SIGAR_AF_INET6) { 753 return; /* prefer ipv4 */ 754 } 755 } 756 else { 757 entry->value = malloc(sizeof(conn->local_address)); 758 } 759 760 memcpy(entry->value, &conn->local_address, 761 sizeof(conn->local_address)); 762} 763 764SIGAR_DECLARE(int) 765sigar_net_listen_address_get(sigar_t *sigar, 766 unsigned long port, 767 sigar_net_address_t *address) 768{ 769 if (!sigar->net_listen || 770 !sigar_cache_find(sigar->net_listen, port)) 771 { 772 sigar_net_stat_t netstat; 773 int status = 774 sigar_net_stat_get(sigar, &netstat, 775 SIGAR_NETCONN_SERVER|SIGAR_NETCONN_TCP); 776 777 if (status != SIGAR_OK) { 778 return status; 779 } 780 } 781 782 if (sigar_cache_find(sigar->net_listen, port)) { 783 void *value = sigar_cache_get(sigar->net_listen, port)->value; 784 memcpy(address, value, sizeof(*address)); 785 return SIGAR_OK; 786 } 787 else { 788 return ENOENT; 789 } 790} 791 792typedef struct { 793 sigar_net_stat_t *netstat; 794 sigar_net_connection_list_t *connlist; 795} net_stat_getter_t; 796 797static int net_stat_walker(sigar_net_connection_walker_t *walker, 798 sigar_net_connection_t *conn) 799{ 800 int state = conn->state; 801 sigar_cache_t *listen_ports = walker->sigar->net_listen; 802 net_stat_getter_t *getter = 803 (net_stat_getter_t *)walker->data; 804 805 if (conn->type == SIGAR_NETCONN_TCP) { 806 getter->netstat->tcp_states[state]++; 807 808 /* XXX listen_ports may get stale */ 809 if (state == SIGAR_TCP_LISTEN) { 810 sigar_net_listen_address_add(walker->sigar, conn); 811 } 812 else { 813 if (sigar_cache_find(listen_ports, 814 conn->local_port)) 815 { 816 getter->netstat->tcp_inbound_total++; 817 } 818 else { 819 getter->netstat->tcp_outbound_total++; 820 } 821 } 822 } 823 else if (conn->type == SIGAR_NETCONN_UDP) { 824 /*XXX*/ 825 } 826 827 getter->netstat->all_inbound_total = 828 getter->netstat->tcp_inbound_total; 829 830 getter->netstat->all_outbound_total = 831 getter->netstat->tcp_outbound_total; 832 833 return SIGAR_OK; 834} 835 836SIGAR_DECLARE(int) 837sigar_net_stat_get(sigar_t *sigar, 838 sigar_net_stat_t *netstat, 839 int flags) 840{ 841 sigar_net_connection_walker_t walker; 842 net_stat_getter_t getter; 843 844 if (!sigar->net_listen) { 845 sigar->net_listen = sigar_cache_new(32); 846 } 847 848 SIGAR_ZERO(netstat); 849 850 getter.netstat = netstat; 851 852 walker.sigar = sigar; 853 walker.data = &getter; 854 walker.add_connection = net_stat_walker; 855 856 walker.flags = flags; 857 858 return sigar_net_connection_walk(&walker); 859} 860 861typedef struct { 862 sigar_net_stat_t *netstat; 863 sigar_net_address_t *address; 864 unsigned long port; 865} net_stat_port_getter_t; 866 867static int net_stat_port_walker(sigar_net_connection_walker_t *walker, 868 sigar_net_connection_t *conn) 869{ 870 net_stat_port_getter_t *getter = 871 (net_stat_port_getter_t *)walker->data; 872 sigar_net_stat_t *netstat = getter->netstat; 873 874 if (conn->type == SIGAR_NETCONN_TCP) { 875 if (conn->local_port == getter->port) { 876 netstat->all_inbound_total++; 877 878 if (sigar_net_address_equals(getter->address, 879 &conn->local_address) == SIGAR_OK) 880 { 881 netstat->tcp_inbound_total++; 882 } 883 } 884 else if (conn->remote_port == getter->port) { 885 netstat->all_outbound_total++; 886 887 if (sigar_net_address_equals(getter->address, 888 &conn->remote_address) == SIGAR_OK) 889 { 890 netstat->tcp_outbound_total++; 891 } 892 } 893 else { 894 return SIGAR_OK; 895 } 896 897 netstat->tcp_states[conn->state]++; 898 } 899 else if (conn->type == SIGAR_NETCONN_UDP) { 900 /*XXX*/ 901 } 902 903 return SIGAR_OK; 904} 905 906SIGAR_DECLARE(int) 907sigar_net_stat_port_get(sigar_t *sigar, 908 sigar_net_stat_t *netstat, 909 int flags, 910 sigar_net_address_t *address, 911 unsigned long port) 912{ 913 sigar_net_connection_walker_t walker; 914 net_stat_port_getter_t getter; 915 916 SIGAR_ZERO(netstat); 917 918 getter.netstat = netstat; 919 getter.address = address; 920 getter.port = port; 921 922 walker.sigar = sigar; 923 walker.data = &getter; 924 walker.add_connection = net_stat_port_walker; 925 926 walker.flags = flags; 927 928 if (SIGAR_LOG_IS_DEBUG(sigar)) { 929 char name[SIGAR_FQDN_LEN]; 930 sigar_net_address_to_string(sigar, address, name); 931 932 sigar_log_printf(sigar, SIGAR_LOG_DEBUG, 933 "[net_stat_port] using address '%s:%d'", 934 name, port); 935 } 936 937 return sigar_net_connection_walk(&walker); 938} 939 940static int tcp_curr_estab_count(sigar_net_connection_walker_t *walker, 941 sigar_net_connection_t *conn) 942{ 943 if ((conn->state == SIGAR_TCP_ESTABLISHED) || 944 (conn->state == SIGAR_TCP_CLOSE_WAIT)) 945 { 946 ((sigar_tcp_t *)walker->data)->curr_estab++; 947 } 948 949 return SIGAR_OK; 950} 951 952/* TCP-MIB::tcpCurrEstab */ 953int sigar_tcp_curr_estab(sigar_t *sigar, sigar_tcp_t *tcp) 954{ 955 sigar_net_connection_walker_t walker; 956 957 walker.sigar = sigar; 958 walker.data = tcp; 959 walker.add_connection = tcp_curr_estab_count; 960 walker.flags = SIGAR_NETCONN_CLIENT|SIGAR_NETCONN_TCP; 961 962 tcp->curr_estab = 0; 963 964 return sigar_net_connection_walk(&walker); 965} 966 967int sigar_arp_list_create(sigar_arp_list_t *arplist) 968{ 969 arplist->number = 0; 970 arplist->size = SIGAR_ARP_LIST_MAX; 971 arplist->data = malloc(sizeof(*(arplist->data)) * 972 arplist->size); 973 return SIGAR_OK; 974} 975 976int sigar_arp_list_grow(sigar_arp_list_t *arplist) 977{ 978 arplist->data = realloc(arplist->data, 979 sizeof(*(arplist->data)) * 980 (arplist->size + SIGAR_ARP_LIST_MAX)); 981 arplist->size += SIGAR_ARP_LIST_MAX; 982 983 return SIGAR_OK; 984} 985 986SIGAR_DECLARE(int) sigar_arp_list_destroy(sigar_t *sigar, 987 sigar_arp_list_t *arplist) 988{ 989 if (arplist->size) { 990 free(arplist->data); 991 arplist->number = arplist->size = 0; 992 } 993 994 return SIGAR_OK; 995} 996 997int sigar_who_list_create(sigar_who_list_t *wholist) 998{ 999 wholist->number = 0; 1000 wholist->size = SIGAR_WHO_LIST_MAX; 1001 wholist->data = malloc(sizeof(*(wholist->data)) * 1002 wholist->size); 1003 return SIGAR_OK; 1004} 1005 1006int sigar_who_list_grow(sigar_who_list_t *wholist) 1007{ 1008 wholist->data = realloc(wholist->data, 1009 sizeof(*(wholist->data)) * 1010 (wholist->size + SIGAR_WHO_LIST_MAX)); 1011 wholist->size += SIGAR_WHO_LIST_MAX; 1012 1013 return SIGAR_OK; 1014} 1015 1016SIGAR_DECLARE(int) sigar_who_list_destroy(sigar_t *sigar, 1017 sigar_who_list_t *wholist) 1018{ 1019 if (wholist->size) { 1020 free(wholist->data); 1021 wholist->number = wholist->size = 0; 1022 } 1023 1024 return SIGAR_OK; 1025} 1026 1027#ifdef DARWIN 1028#include <AvailabilityMacros.h> 1029#endif 1030#ifdef MAC_OS_X_VERSION_10_5 1031# if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 1032# define SIGAR_NO_UTMP 1033# endif 1034/* else 10.4 and earlier or compiled with -mmacosx-version-min=10.3 */ 1035#endif 1036 1037#if defined(__sun) 1038# include <utmpx.h> 1039# define SIGAR_UTMP_FILE _UTMPX_FILE 1040# define ut_time ut_tv.tv_sec 1041#elif defined(WIN32) 1042/* XXX may not be the default */ 1043#define SIGAR_UTMP_FILE "C:\\cygwin\\var\\run\\utmp" 1044#define UT_LINESIZE 16 1045#define UT_NAMESIZE 16 1046#define UT_HOSTSIZE 256 1047#define UT_IDLEN 2 1048#define ut_name ut_user 1049 1050struct utmp { 1051 short ut_type; 1052 int ut_pid; 1053 char ut_line[UT_LINESIZE]; 1054 char ut_id[UT_IDLEN]; 1055 time_t ut_time; 1056 char ut_user[UT_NAMESIZE]; 1057 char ut_host[UT_HOSTSIZE]; 1058 long ut_addr; 1059}; 1060#elif defined(NETWARE) 1061static char *getpass(const char *prompt) 1062{ 1063 static char password[BUFSIZ]; 1064 1065 fputs(prompt, stderr); 1066 fgets((char *)&password, sizeof(password), stdin); 1067 1068 return (char *)&password; 1069} 1070#elif !defined(SIGAR_NO_UTMP) 1071# include <utmp.h> 1072# ifdef UTMP_FILE 1073# define SIGAR_UTMP_FILE UTMP_FILE 1074# else 1075# define SIGAR_UTMP_FILE _PATH_UTMP 1076# endif 1077#endif 1078 1079#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(DARWIN) 1080# define ut_user ut_name 1081#endif 1082 1083#ifdef DARWIN 1084/* XXX from utmpx.h; sizeof changed in 10.5 */ 1085/* additionally, utmpx does not work on 10.4 */ 1086#define SIGAR_HAS_UTMPX 1087#define _PATH_UTMPX "/var/run/utmpx" 1088#define _UTX_USERSIZE 256 /* matches MAXLOGNAME */ 1089#define _UTX_LINESIZE 32 1090#define _UTX_IDSIZE 4 1091#define _UTX_HOSTSIZE 256 1092struct utmpx { 1093 char ut_user[_UTX_USERSIZE]; /* login name */ 1094 char ut_id[_UTX_IDSIZE]; /* id */ 1095 char ut_line[_UTX_LINESIZE]; /* tty name */ 1096 pid_t ut_pid; /* process id creating the entry */ 1097 short ut_type; /* type of this entry */ 1098 struct timeval ut_tv; /* time entry was created */ 1099 char ut_host[_UTX_HOSTSIZE]; /* host name */ 1100 __uint32_t ut_pad[16]; /* reserved for future use */ 1101}; 1102#define ut_xtime ut_tv.tv_sec 1103#define UTMPX_USER_PROCESS 7 1104/* end utmpx.h */ 1105#define SIGAR_UTMPX_FILE _PATH_UTMPX 1106#endif 1107 1108#if !defined(NETWARE) && !defined(_AIX) 1109 1110#define WHOCPY(dest, src) \ 1111 SIGAR_SSTRCPY(dest, src); \ 1112 if (sizeof(src) < sizeof(dest)) \ 1113 dest[sizeof(src)] = '\0' 1114 1115#ifdef SIGAR_HAS_UTMPX 1116static int sigar_who_utmpx(sigar_t *sigar, 1117 sigar_who_list_t *wholist) 1118{ 1119 FILE *fp; 1120 struct utmpx ut; 1121 1122 if (!(fp = fopen(SIGAR_UTMPX_FILE, "r"))) { 1123 return errno; 1124 } 1125 1126 while (fread(&ut, sizeof(ut), 1, fp) == 1) { 1127 sigar_who_t *who; 1128 1129 if (*ut.ut_user == '\0') { 1130 continue; 1131 } 1132 1133#ifdef UTMPX_USER_PROCESS 1134 if (ut.ut_type != UTMPX_USER_PROCESS) { 1135 continue; 1136 } 1137#endif 1138 1139 SIGAR_WHO_LIST_GROW(wholist); 1140 who = &wholist->data[wholist->number++]; 1141 1142 WHOCPY(who->user, ut.ut_user); 1143 WHOCPY(who->device, ut.ut_line); 1144 WHOCPY(who->host, ut.ut_host); 1145 1146 who->time = ut.ut_xtime; 1147 } 1148 1149 fclose(fp); 1150 1151 return SIGAR_OK; 1152} 1153#endif 1154 1155#if defined(SIGAR_NO_UTMP) && defined(SIGAR_HAS_UTMPX) 1156#define sigar_who_utmp sigar_who_utmpx 1157#else 1158static int sigar_who_utmp(sigar_t *sigar, 1159 sigar_who_list_t *wholist) 1160{ 1161 FILE *fp; 1162#ifdef __sun 1163 /* use futmpx w/ pid32_t for sparc64 */ 1164 struct futmpx ut; 1165#else 1166 struct utmp ut; 1167#endif 1168 if (!(fp = fopen(SIGAR_UTMP_FILE, "r"))) { 1169#ifdef SIGAR_HAS_UTMPX 1170 /* Darwin 10.5 */ 1171 return sigar_who_utmpx(sigar, wholist); 1172#endif 1173 return errno; 1174 } 1175 1176 while (fread(&ut, sizeof(ut), 1, fp) == 1) { 1177 sigar_who_t *who; 1178 1179 if (*ut.ut_name == '\0') { 1180 continue; 1181 } 1182 1183#ifdef USER_PROCESS 1184 if (ut.ut_type != USER_PROCESS) { 1185 continue; 1186 } 1187#endif 1188 1189 SIGAR_WHO_LIST_GROW(wholist); 1190 who = &wholist->data[wholist->number++]; 1191 1192 WHOCPY(who->user, ut.ut_user); 1193 WHOCPY(who->device, ut.ut_line); 1194 WHOCPY(who->host, ut.ut_host); 1195 1196 who->time = ut.ut_time; 1197 } 1198 1199 fclose(fp); 1200 1201 return SIGAR_OK; 1202} 1203#endif /* SIGAR_NO_UTMP */ 1204#endif /* NETWARE */ 1205 1206#if defined(WIN32) 1207 1208int sigar_who_list_get_win32(sigar_t *sigar, 1209 sigar_who_list_t *wholist); 1210 1211SIGAR_DECLARE(int) sigar_who_list_get(sigar_t *sigar, 1212 sigar_who_list_t *wholist) 1213{ 1214 sigar_who_list_create(wholist); 1215 1216 /* cygwin ssh */ 1217 sigar_who_utmp(sigar, wholist); 1218 1219 sigar_who_list_get_win32(sigar, wholist); 1220 1221 return SIGAR_OK; 1222} 1223 1224SIGAR_DECLARE(int) sigar_resource_limit_get(sigar_t *sigar, 1225 sigar_resource_limit_t *rlimit) 1226{ 1227 MEMORY_BASIC_INFORMATION meminfo; 1228 memset(rlimit, 0x7fffffff, sizeof(*rlimit)); 1229 1230 if (VirtualQuery((LPCVOID)&meminfo, &meminfo, sizeof(meminfo))) { 1231 rlimit->stack_cur = 1232 (DWORD)&meminfo - (DWORD)meminfo.AllocationBase; 1233 rlimit->stack_max = 1234 ((DWORD)meminfo.BaseAddress + meminfo.RegionSize) - 1235 (DWORD)meminfo.AllocationBase; 1236 } 1237 1238 rlimit->virtual_memory_max = rlimit->virtual_memory_cur = 1239 0x80000000UL; 1240 1241 return SIGAR_OK; 1242} 1243 1244#elif defined(NETWARE) 1245int sigar_resource_limit_get(sigar_t *sigar, 1246 sigar_resource_limit_t *rlimit) 1247{ 1248 return SIGAR_ENOTIMPL; 1249} 1250 1251int sigar_who_list_get(sigar_t *sigar, 1252 sigar_who_list_t *wholist) 1253{ 1254 return SIGAR_ENOTIMPL; 1255} 1256#else 1257 1258#ifndef _AIX 1259int sigar_who_list_get(sigar_t *sigar, 1260 sigar_who_list_t *wholist) 1261{ 1262 int status; 1263 1264 sigar_who_list_create(wholist); 1265 1266 status = sigar_who_utmp(sigar, wholist); 1267 if (status != SIGAR_OK) { 1268 sigar_who_list_destroy(sigar, wholist); 1269 return status; 1270 } 1271 1272 return SIGAR_OK; 1273} 1274#endif 1275 1276static int sigar_get_default_gateway(sigar_t *sigar, 1277 sigar_net_info_t *netinfo) 1278{ 1279 int status, i; 1280 sigar_net_route_list_t routelist; 1281 1282 status = sigar_net_route_list_get(sigar, &routelist); 1283 if (status != SIGAR_OK) { 1284 return status; 1285 } 1286 1287 for (i=0; i<routelist.number; i++) { 1288 if ((routelist.data[i].flags & SIGAR_RTF_GATEWAY) && 1289 (routelist.data[i].destination.addr.in == 0)) 1290 { 1291 sigar_net_address_to_string(sigar, 1292 &routelist.data[i].gateway, 1293 netinfo->default_gateway); 1294 1295 SIGAR_STRNCPY(netinfo->default_gateway_interface, 1296 routelist.data[i].ifname, 1297 sizeof(netinfo->default_gateway_interface)); 1298 break; 1299 } 1300 } 1301 1302 sigar_net_route_list_destroy(sigar, &routelist); 1303 1304 return SIGAR_OK; 1305} 1306 1307int sigar_net_info_get(sigar_t *sigar, 1308 sigar_net_info_t *netinfo) 1309{ 1310 int size; 1311 char buffer[BUFSIZ], *ptr; 1312 FILE *fp; 1313 1314 SIGAR_ZERO(netinfo); 1315 1316 if ((fp = fopen("/etc/resolv.conf", "r"))) { 1317 while ((ptr = fgets(buffer, sizeof(buffer), fp))) { 1318 int len; 1319 1320 SIGAR_SKIP_SPACE(ptr); 1321 if ((*ptr == '#') || 1322 !(ptr = strstr(ptr, "nameserver"))) 1323 { 1324 continue; 1325 } 1326 ptr += 10; 1327 SIGAR_SKIP_SPACE(ptr); 1328 1329 len = strlen(ptr); 1330 ptr[len-1] = '\0'; /* chop \n */ 1331 1332 if (!netinfo->primary_dns[0]) { 1333 SIGAR_SSTRCPY(netinfo->primary_dns, ptr); 1334 } 1335 else if (!netinfo->secondary_dns[0]) { 1336 SIGAR_SSTRCPY(netinfo->secondary_dns, ptr); 1337 } 1338 else { 1339 break; 1340 } 1341 } 1342 fclose(fp); 1343 } /* else /etc/resolv.conf may not exist if unplugged (MacOSX) */ 1344 1345 size = sizeof(netinfo->host_name)-1; 1346 if (gethostname(netinfo->host_name, size) == 0) { 1347 netinfo->host_name[size] = '\0'; 1348 } 1349 else { 1350 netinfo->host_name[0] = '\0'; 1351 } 1352 1353 size = sizeof(netinfo->domain_name)-1; 1354 if (getdomainname(netinfo->domain_name, size) == 0) { 1355 netinfo->domain_name[size] = '\0'; 1356 } 1357 else { 1358 netinfo->domain_name[0] = '\0'; 1359 } 1360 1361 sigar_get_default_gateway(sigar, netinfo); 1362 1363 return SIGAR_OK; 1364} 1365 1366#include <sys/resource.h> 1367 1368#define OffsetOf(structure, field) \ 1369 (size_t)(&((structure *)NULL)->field) 1370 1371#define RlimitOffsets(field) \ 1372 OffsetOf(sigar_resource_limit_t, field##_cur), \ 1373 OffsetOf(sigar_resource_limit_t, field##_max) 1374 1375#define RlimitSet(structure, ptr, val) \ 1376 *(sigar_uint64_t *)((char *)structure + (int)(long)ptr) = val 1377 1378typedef struct { 1379 int resource; 1380 int factor; 1381 size_t cur; 1382 size_t max; 1383} rlimit_field_t; 1384 1385#ifndef RLIMIT_RSS 1386#define RLIMIT_RSS (RLIM_NLIMITS+1) 1387#endif 1388 1389#ifndef RLIMIT_NPROC 1390#define RLIMIT_NPROC (RLIM_NLIMITS+2) 1391#endif 1392 1393#define RLIMIT_PSIZE (RLIM_NLIMITS+3) 1394 1395#ifndef RLIMIT_AS 1396# if defined(RLIMIT_VMEM) 1397# define RLIMIT_AS RLIMIT_VMEM 1398# elif defined(RLIMIT_RSS) 1399# define RLIMIT_AS RLIMIT_RSS 1400# endif 1401#endif 1402 1403static rlimit_field_t sigar_rlimits[] = { 1404 { RLIMIT_CPU, 1, RlimitOffsets(cpu) }, 1405 { RLIMIT_FSIZE, 1024, RlimitOffsets(file_size) }, 1406 { RLIMIT_DATA, 1024, RlimitOffsets(data) }, 1407 { RLIMIT_STACK, 1024, RlimitOffsets(stack) }, 1408 { RLIMIT_PSIZE, 512, RlimitOffsets(pipe_size) }, 1409 { RLIMIT_CORE, 1024, RlimitOffsets(core) }, 1410 { RLIMIT_RSS, 1024, RlimitOffsets(memory) }, 1411 { RLIMIT_NPROC, 1, RlimitOffsets(processes) }, 1412 { RLIMIT_NOFILE, 1, RlimitOffsets(open_files) }, 1413 { RLIMIT_AS, 1024, RlimitOffsets(virtual_memory) }, 1414 { -1 } 1415}; 1416 1417#define RlimitScale(val) \ 1418 if (val != RLIM_INFINITY) val /= r->factor 1419 1420#define RlimitHS(val) \ 1421 rl.rlim_cur = rl.rlim_max = (val) 1422 1423int sigar_resource_limit_get(sigar_t *sigar, 1424 sigar_resource_limit_t *rlimit) 1425{ 1426 int i; 1427 1428 for (i=0; sigar_rlimits[i].resource != -1; i++) { 1429 struct rlimit rl; 1430 rlimit_field_t *r = &sigar_rlimits[i]; 1431 1432 if (r->resource > RLIM_NLIMITS) { 1433 switch (r->resource) { 1434 case RLIMIT_NPROC: 1435 RlimitHS(sysconf(_SC_CHILD_MAX)); 1436 break; 1437 case RLIMIT_PSIZE: 1438 RlimitHS(PIPE_BUF/512); 1439 break; 1440 default: 1441 RlimitHS(RLIM_INFINITY); 1442 break; 1443 } 1444 } 1445 else if (getrlimit(r->resource, &rl) != 0) { 1446 RlimitHS(RLIM_INFINITY); 1447 } 1448 else { 1449 RlimitScale(rl.rlim_cur); 1450 RlimitScale(rl.rlim_max); 1451 } 1452 1453 RlimitSet(rlimit, r->cur, rl.rlim_cur); 1454 RlimitSet(rlimit, r->max, rl.rlim_max); 1455 } 1456 1457 return SIGAR_OK; 1458} 1459#endif 1460 1461#ifdef HAVE_LIBDLPI_H 1462#include <libdlpi.h> 1463 1464static void hwaddr_libdlpi_lookup(sigar_t *sigar, sigar_net_interface_config_t *ifconfig) 1465{ 1466 dlpi_handle_t handle; 1467 dlpi_info_t linkinfo; 1468 uchar_t addr[DLPI_PHYSADDR_MAX]; 1469 uint_t alen = sizeof(addr); 1470 1471 if (dlpi_open(ifconfig->name, &handle, 0) != DLPI_SUCCESS) { 1472 return; 1473 } 1474 1475 if (dlpi_get_physaddr(handle, DL_CURR_PHYS_ADDR, addr, &alen) == DLPI_SUCCESS && 1476 dlpi_info(handle, &linkinfo, 0) == DLPI_SUCCESS) { 1477 if (alen < sizeof(ifconfig->hwaddr.addr.mac)) { 1478 sigar_net_address_mac_set(ifconfig->hwaddr, addr, alen); 1479 SIGAR_SSTRCPY(ifconfig->type, dlpi_mactype(linkinfo.di_mactype)); 1480 } 1481 } 1482 1483 dlpi_close(handle); 1484} 1485#endif 1486 1487 1488#if !defined(WIN32) && !defined(NETWARE) && !defined(DARWIN) && \ 1489 !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) 1490 1491/* XXX: prolly will be moving these stuffs into os_net.c */ 1492#include <sys/ioctl.h> 1493#include <net/if.h> 1494 1495#ifndef SIOCGIFCONF 1496#include <sys/sockio.h> 1497#endif 1498 1499#if defined(_AIX) || defined(__osf__) /* good buddies */ 1500 1501#include <net/if_dl.h> 1502 1503static void hwaddr_aix_lookup(sigar_t *sigar, sigar_net_interface_config_t *ifconfig) 1504{ 1505 char *ent, *end; 1506 struct ifreq *ifr; 1507 1508 /* XXX: assumes sigar_net_interface_list_get has been called */ 1509 end = sigar->ifconf_buf + sigar->ifconf_len; 1510 1511 for (ent = sigar->ifconf_buf; 1512 ent < end; 1513 ent += sizeof(*ifr)) 1514 { 1515 ifr = (struct ifreq *)ent; 1516 1517 if (ifr->ifr_addr.sa_family != AF_LINK) { 1518 continue; 1519 } 1520 1521 if (strEQ(ifr->ifr_name, ifconfig->name)) { 1522 struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr; 1523 1524 sigar_net_address_mac_set(ifconfig->hwaddr, 1525 LLADDR(sdl), 1526 sdl->sdl_alen); 1527 return; 1528 } 1529 } 1530 1531 sigar_hwaddr_set_null(ifconfig); 1532} 1533 1534#elif !defined(SIOCGIFHWADDR) 1535 1536#include <net/if_arp.h> 1537 1538static void hwaddr_arp_lookup(sigar_net_interface_config_t *ifconfig, int sock) 1539{ 1540 struct arpreq areq; 1541 struct sockaddr_in *sa; 1542 1543 memset(&areq, 0, sizeof(areq)); 1544 sa = (struct sockaddr_in *)&areq.arp_pa; 1545 sa->sin_family = AF_INET; 1546 sa->sin_addr.s_addr = ifconfig->address.addr.in; 1547 1548 if (ioctl(sock, SIOCGARP, &areq) < 0) { 1549 /* ho-hum */ 1550 sigar_hwaddr_set_null(ifconfig); 1551 } 1552 else { 1553 sigar_net_address_mac_set(ifconfig->hwaddr, 1554 areq.arp_ha.sa_data, 1555 SIGAR_IFHWADDRLEN); 1556 } 1557} 1558 1559#endif 1560 1561#ifdef __linux__ 1562 1563#include <net/if_arp.h> 1564 1565#ifndef ARPHRD_CISCO /* not in 2.2 kernel headers */ 1566#define ARPHRD_CISCO 513 /* Cisco HDLC. */ 1567#endif 1568 1569static void get_interface_type(sigar_net_interface_config_t *ifconfig, 1570 int family) 1571{ 1572 char *type; 1573 1574 switch (family) { 1575 case ARPHRD_SLIP: 1576 type = SIGAR_NIC_SLIP; 1577 break; 1578 case ARPHRD_CSLIP: 1579 type = SIGAR_NIC_CSLIP; 1580 break; 1581 case ARPHRD_SLIP6: 1582 type = SIGAR_NIC_SLIP6; 1583 break; 1584 case ARPHRD_CSLIP6: 1585 type = SIGAR_NIC_CSLIP6; 1586 break; 1587 case ARPHRD_ADAPT: 1588 type = SIGAR_NIC_ADAPTIVE; 1589 break; 1590 case ARPHRD_ETHER: 1591 type = SIGAR_NIC_ETHERNET; 1592 break; 1593 case ARPHRD_ASH: 1594 type = SIGAR_NIC_ASH; 1595 break; 1596 case ARPHRD_FDDI: 1597 type = SIGAR_NIC_FDDI; 1598 break; 1599 case ARPHRD_HIPPI: 1600 type = SIGAR_NIC_HIPPI; 1601 break; 1602 case ARPHRD_AX25: 1603 type = SIGAR_NIC_AX25; 1604 break; 1605 case ARPHRD_ROSE: 1606 type = SIGAR_NIC_ROSE; 1607 break; 1608 case ARPHRD_NETROM: 1609 type = SIGAR_NIC_NETROM; 1610 break; 1611 case ARPHRD_X25: 1612 type = SIGAR_NIC_X25; 1613 break; 1614 case ARPHRD_TUNNEL: 1615 type = SIGAR_NIC_TUNNEL; 1616 break; 1617 case ARPHRD_PPP: 1618 type = SIGAR_NIC_PPP; 1619 break; 1620 case ARPHRD_CISCO: 1621 type = SIGAR_NIC_HDLC; 1622 break; 1623 case ARPHRD_LAPB: 1624 type = SIGAR_NIC_LAPB; 1625 break; 1626 case ARPHRD_ARCNET: 1627 type = SIGAR_NIC_ARCNET; 1628 break; 1629 case ARPHRD_DLCI: 1630 type = SIGAR_NIC_DLCI; 1631 break; 1632 case ARPHRD_FRAD: 1633 type = SIGAR_NIC_FRAD; 1634 break; 1635 case ARPHRD_SIT: 1636 type = SIGAR_NIC_SIT; 1637 break; 1638 case ARPHRD_IRDA: 1639 type = SIGAR_NIC_IRDA; 1640 break; 1641 case ARPHRD_ECONET: 1642 type = SIGAR_NIC_EC; 1643 break; 1644 default: 1645 type = SIGAR_NIC_UNSPEC; 1646 break; 1647 } 1648 1649 SIGAR_SSTRCPY(ifconfig->type, type); 1650} 1651 1652#endif 1653 1654int sigar_net_interface_config_get(sigar_t *sigar, const char *name, 1655 sigar_net_interface_config_t *ifconfig) 1656{ 1657 int sock; 1658 struct ifreq ifr; 1659 1660 if (!name) { 1661 return sigar_net_interface_config_primary_get(sigar, ifconfig); 1662 } 1663 1664 SIGAR_ZERO(ifconfig); 1665 1666 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 1667 return errno; 1668 } 1669 1670 SIGAR_SSTRCPY(ifconfig->name, name); 1671 SIGAR_SSTRCPY(ifr.ifr_name, name); 1672 1673#define ifr_s_addr(ifr) \ 1674 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr 1675 1676 if (!ioctl(sock, SIOCGIFADDR, &ifr)) { 1677 sigar_net_address_set(ifconfig->address, 1678 ifr_s_addr(ifr)); 1679 } 1680 1681 if (!ioctl(sock, SIOCGIFNETMASK, &ifr)) { 1682 sigar_net_address_set(ifconfig->netmask, 1683 ifr_s_addr(ifr)); 1684 } 1685 1686 if (!ioctl(sock, SIOCGIFFLAGS, &ifr)) { 1687 sigar_uint64_t flags = ifr.ifr_flags; 1688#ifdef __linux__ 1689# ifndef IFF_DYNAMIC 1690# define IFF_DYNAMIC 0x8000 /* not in 2.2 kernel */ 1691# endif /* IFF_DYNAMIC */ 1692 int is_mcast = flags & IFF_MULTICAST; 1693 int is_slave = flags & IFF_SLAVE; 1694 int is_master = flags & IFF_MASTER; 1695 int is_dynamic = flags & IFF_DYNAMIC; 1696 /* 1697 * XXX: should just define SIGAR_IFF_* 1698 * and test IFF_* bits on given platform. 1699 * this is the only diff between solaris/hpux/linux 1700 * for the flags we care about. 1701 * 1702 */ 1703 flags &= ~(IFF_MULTICAST|IFF_SLAVE|IFF_MASTER); 1704 if (is_mcast) { 1705 flags |= SIGAR_IFF_MULTICAST; 1706 } 1707 if (is_slave) { 1708 flags |= SIGAR_IFF_SLAVE; 1709 } 1710 if (is_master) { 1711 flags |= SIGAR_IFF_MASTER; 1712 } 1713 if (is_dynamic) { 1714 flags |= SIGAR_IFF_DYNAMIC; 1715 } 1716#endif 1717 ifconfig->flags = flags; 1718 } 1719 else { 1720 /* should always be able to get flags for existing device */ 1721 /* other ioctls may fail if device is not enabled: ok */ 1722 close(sock); 1723 return errno; 1724 } 1725 1726 if (ifconfig->flags & IFF_LOOPBACK) { 1727 sigar_net_address_set(ifconfig->destination, 1728 ifconfig->address.addr.in); 1729 sigar_net_address_set(ifconfig->broadcast, 0); 1730 sigar_hwaddr_set_null(ifconfig); 1731 SIGAR_SSTRCPY(ifconfig->type, 1732 SIGAR_NIC_LOOPBACK); 1733 } 1734 else { 1735 if (!ioctl(sock, SIOCGIFDSTADDR, &ifr)) { 1736 sigar_net_address_set(ifconfig->destination, 1737 ifr_s_addr(ifr)); 1738 } 1739 1740 if (!ioctl(sock, SIOCGIFBRDADDR, &ifr)) { 1741 sigar_net_address_set(ifconfig->broadcast, 1742 ifr_s_addr(ifr)); 1743 } 1744 1745#if defined(HAVE_LIBDLPI_H) 1746 hwaddr_libdlpi_lookup(sigar, ifconfig); 1747#elif defined(SIOCGIFHWADDR) 1748 if (!ioctl(sock, SIOCGIFHWADDR, &ifr)) { 1749 get_interface_type(ifconfig, 1750 ifr.ifr_hwaddr.sa_family); 1751 sigar_net_address_mac_set(ifconfig->hwaddr, 1752 ifr.ifr_hwaddr.sa_data, 1753 IFHWADDRLEN); 1754 } 1755#elif defined(_AIX) || defined(__osf__) 1756 hwaddr_aix_lookup(sigar, ifconfig); 1757 SIGAR_SSTRCPY(ifconfig->type, 1758 SIGAR_NIC_ETHERNET); 1759#else 1760 hwaddr_arp_lookup(ifconfig, sock); 1761 SIGAR_SSTRCPY(ifconfig->type, 1762 SIGAR_NIC_ETHERNET); 1763#endif 1764 } 1765 1766#if defined(SIOCGLIFMTU) && !defined(__hpux) 1767 { 1768 struct lifreq lifr; 1769 SIGAR_SSTRCPY(lifr.lifr_name, name); 1770 if(!ioctl(sock, SIOCGLIFMTU, &lifr)) { 1771 ifconfig->mtu = lifr.lifr_mtu; 1772 } 1773 } 1774#elif defined(SIOCGIFMTU) 1775 if (!ioctl(sock, SIOCGIFMTU, &ifr)) { 1776# if defined(__hpux) 1777 ifconfig->mtu = ifr.ifr_metric; 1778# else 1779 ifconfig->mtu = ifr.ifr_mtu; 1780#endif 1781 } 1782#else 1783 ifconfig->mtu = 0; /*XXX*/ 1784#endif 1785 1786 if (!ioctl(sock, SIOCGIFMETRIC, &ifr)) { 1787 ifconfig->metric = ifr.ifr_metric ? ifr.ifr_metric : 1; 1788 } 1789 1790#if defined(SIOCGIFTXQLEN) 1791 if (!ioctl(sock, SIOCGIFTXQLEN, &ifr)) { 1792 ifconfig->tx_queue_len = ifr.ifr_qlen; 1793 } 1794 else { 1795 ifconfig->tx_queue_len = -1; /* net-tools behaviour */ 1796 } 1797#else 1798 ifconfig->tx_queue_len = -1; 1799#endif 1800 1801 close(sock); 1802 1803 /* XXX can we get a better description like win32? */ 1804 SIGAR_SSTRCPY(ifconfig->description, 1805 ifconfig->name); 1806 1807 sigar_net_interface_ipv6_config_init(ifconfig); 1808 sigar_net_interface_ipv6_config_get(sigar, name, ifconfig); 1809 1810 return SIGAR_OK; 1811} 1812 1813#ifdef _AIX 1814# define MY_SIOCGIFCONF CSIOCGIFCONF 1815#else 1816# define MY_SIOCGIFCONF SIOCGIFCONF 1817#endif 1818 1819#ifdef __osf__ 1820static int sigar_netif_configured(sigar_t *sigar, char *name) 1821{ 1822 int status; 1823 sigar_net_interface_config_t ifconfig; 1824 1825 status = sigar_net_interface_config_get(sigar, name, &ifconfig); 1826 1827 return status == SIGAR_OK; 1828} 1829#endif 1830 1831#ifdef __linux__ 1832static int has_interface(sigar_net_interface_list_t *iflist, 1833 char *name) 1834{ 1835 register int i; 1836 register int num = iflist->number; 1837 register char **data = iflist->data; 1838 for (i=0; i<num; i++) { 1839 if (strEQ(name, data[i])) { 1840 return 1; 1841 } 1842 } 1843 return 0; 1844} 1845 1846static int proc_net_interface_list_get(sigar_t *sigar, 1847 sigar_net_interface_list_t *iflist) 1848{ 1849 /* certain interfaces such as VMware vmnic 1850 * are not returned by ioctl(SIOCGIFCONF). 1851 * check /proc/net/dev for any ioctl missed. 1852 */ 1853 char buffer[BUFSIZ]; 1854 FILE *fp = fopen("/proc/net/dev", "r"); 1855 1856 if (!fp) { 1857 return errno; 1858 } 1859 1860 /* skip header */ 1861 fgets(buffer, sizeof(buffer), fp); 1862 fgets(buffer, sizeof(buffer), fp); 1863 1864 while (fgets(buffer, sizeof(buffer), fp)) { 1865 char *ptr, *dev; 1866 1867 dev = buffer; 1868 while (isspace(*dev)) { 1869 dev++; 1870 } 1871 1872 if (!(ptr = strchr(dev, ':'))) { 1873 continue; 1874 } 1875 1876 *ptr++ = 0; 1877 1878 if (has_interface(iflist, dev)) { 1879 continue; 1880 } 1881 1882 SIGAR_NET_IFLIST_GROW(iflist); 1883 1884 iflist->data[iflist->number++] = 1885 sigar_strdup(dev); 1886 } 1887 1888 fclose(fp); 1889 1890 return SIGAR_OK; 1891} 1892#endif 1893 1894int sigar_net_interface_list_get(sigar_t *sigar, 1895 sigar_net_interface_list_t *iflist) 1896{ 1897 int n, lastlen=0; 1898 struct ifreq *ifr; 1899 struct ifconf ifc; 1900 int sock = socket(AF_INET, SOCK_DGRAM, 0); 1901 1902 if (sock < 0) { 1903 return errno; 1904 } 1905 1906 for (;;) { 1907 if (!sigar->ifconf_buf || lastlen) { 1908 sigar->ifconf_len += sizeof(struct ifreq) * SIGAR_NET_IFLIST_MAX; 1909 sigar->ifconf_buf = realloc(sigar->ifconf_buf, sigar->ifconf_len); 1910 } 1911 1912 ifc.ifc_len = sigar->ifconf_len; 1913 ifc.ifc_buf = sigar->ifconf_buf; 1914 1915 if (ioctl(sock, MY_SIOCGIFCONF, &ifc) < 0) { 1916 /* EINVAL should mean num_interfaces > ifc.ifc_len */ 1917 if ((errno != EINVAL) || 1918 (lastlen == ifc.ifc_len)) 1919 { 1920 free(ifc.ifc_buf); 1921 return errno; 1922 } 1923 } 1924 1925 if (ifc.ifc_len < sigar->ifconf_len) { 1926 break; /* got em all */ 1927 } 1928 1929 if (ifc.ifc_len != lastlen) { 1930 /* might be more */ 1931 lastlen = ifc.ifc_len; 1932 continue; 1933 } 1934 1935 break; 1936 } 1937 1938 close(sock); 1939 1940 iflist->number = 0; 1941 iflist->size = ifc.ifc_len; 1942 iflist->data = malloc(sizeof(*(iflist->data)) * 1943 iflist->size); 1944 1945 ifr = ifc.ifc_req; 1946 for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq), ifr++) { 1947#if defined(_AIX) || defined(__osf__) /* pass the bourbon */ 1948 if (ifr->ifr_addr.sa_family != AF_LINK) { 1949 /* XXX: dunno if this is right. 1950 * otherwise end up with two 'en0' and three 'lo0' 1951 * with the same ip address. 1952 */ 1953 continue; 1954 } 1955# ifdef __osf__ 1956 /* weed out "sl0", "tun0" and the like */ 1957 /* XXX must be a better way to check this */ 1958 if (!sigar_netif_configured(sigar, ifr->ifr_name)) { 1959 continue; 1960 } 1961# endif 1962#endif 1963 iflist->data[iflist->number++] = 1964 sigar_strdup(ifr->ifr_name); 1965 } 1966 1967#ifdef __linux__ 1968 proc_net_interface_list_get(sigar, iflist); 1969#endif 1970 1971 return SIGAR_OK; 1972} 1973 1974#endif /* WIN32 */ 1975 1976SIGAR_DECLARE(int) 1977sigar_net_interface_config_primary_get(sigar_t *sigar, 1978 sigar_net_interface_config_t *ifconfig) 1979{ 1980 int i, status, found=0; 1981 sigar_net_interface_list_t iflist; 1982 sigar_net_interface_config_t possible_config; 1983 1984 possible_config.flags = 0; 1985 1986 if ((status = sigar_net_interface_list_get(sigar, &iflist)) != SIGAR_OK) { 1987 return status; 1988 } 1989 1990 for (i=0; i<iflist.number; i++) { 1991 status = sigar_net_interface_config_get(sigar, 1992 iflist.data[i], ifconfig); 1993 1994 if ((status != SIGAR_OK) || 1995 (ifconfig->flags & SIGAR_IFF_LOOPBACK) || 1996 !ifconfig->hwaddr.addr.in) /* no mac address */ 1997 { 1998 continue; 1999 } 2000 2001 if (!possible_config.flags) { 2002 /* save for later for use if we're not connected to the net 2003 * or all interfaces are aliases (e.g. solaris zone) 2004 */ 2005 memcpy(&possible_config, ifconfig, sizeof(*ifconfig)); 2006 } 2007 if (!ifconfig->address.addr.in) { 2008 continue; /* no ip address */ 2009 } 2010 if (strchr(iflist.data[i], ':')) { 2011 continue; /* alias */ 2012 } 2013 2014 found = 1; 2015 break; 2016 } 2017 2018 sigar_net_interface_list_destroy(sigar, &iflist); 2019 2020 if (found) { 2021 return SIGAR_OK; 2022 } 2023 else if (possible_config.flags) { 2024 memcpy(ifconfig, &possible_config, sizeof(*ifconfig)); 2025 return SIGAR_OK; 2026 } 2027 else { 2028 return SIGAR_ENXIO; 2029 } 2030} 2031 2032static int fqdn_ip_get(sigar_t *sigar, char *name) 2033{ 2034 sigar_net_interface_config_t ifconfig; 2035 int status; 2036 2037 status = sigar_net_interface_config_primary_get(sigar, &ifconfig); 2038 2039 if (status != SIGAR_OK) { 2040 return status; 2041 } 2042 if (!ifconfig.address.addr.in) { 2043 return SIGAR_ENXIO; 2044 } 2045 2046 sigar_net_address_to_string(sigar, &ifconfig.address, name); 2047 2048 sigar_log_printf(sigar, SIGAR_LOG_DEBUG, 2049 "[fqdn] using ip address '%s' for fqdn", 2050 name); 2051 2052 return SIGAR_OK; 2053} 2054 2055struct hostent *sigar_gethostbyname(const char *name, 2056 sigar_hostent_t *data) 2057{ 2058 struct hostent *hp = NULL; 2059 2060#if defined(__linux__) 2061 gethostbyname_r(name, &data->hs, 2062 data->buffer, sizeof(data->buffer), 2063 &hp, &data->error); 2064#elif defined(__sun) 2065 hp = gethostbyname_r(name, &data->hs, 2066 data->buffer, sizeof(data->buffer), 2067 &data->error); 2068#elif defined(SIGAR_HAS_HOSTENT_DATA) 2069 if (gethostbyname_r(name, &data->hs, &data->hd) == 0) { 2070 hp = &data->hs; 2071 } 2072 else { 2073 data->error = h_errno; 2074 } 2075#else 2076 hp = gethostbyname(name); 2077#endif 2078 2079 return hp; 2080} 2081 2082static struct hostent *sigar_gethostbyaddr(const char *addr, 2083 int len, int type, 2084 sigar_hostent_t *data) 2085{ 2086 struct hostent *hp = NULL; 2087 2088#if defined(__linux__) 2089 gethostbyaddr_r(addr, len, type, 2090 &data->hs, 2091 data->buffer, sizeof(data->buffer), 2092 &hp, &data->error); 2093#elif defined(__sun) 2094 hp = gethostbyaddr_r(addr, len, type, 2095 &data->hs, 2096 data->buffer, sizeof(data->buffer), 2097 &data->error); 2098#elif defined(SIGAR_HAS_HOSTENT_DATA) 2099 if (gethostbyaddr_r((char *)addr, len, type, 2100 &data->hs, &data->hd) == 0) 2101 { 2102 hp = &data->hs; 2103 } 2104 else { 2105 data->error = h_errno; 2106 } 2107#else 2108 if (!(hp = gethostbyaddr(addr, len, type))) { 2109 data->error = h_errno; 2110 } 2111#endif 2112 2113 return hp; 2114} 2115#define IS_FQDN(name) \ 2116 (name && strchr(name, '.')) 2117 2118#define IS_FQDN_MATCH(lookup, name) \ 2119 (IS_FQDN(lookup) && strnEQ(lookup, name, strlen(name))) 2120 2121#define FQDN_SET(fqdn) \ 2122 SIGAR_STRNCPY(name, fqdn, namelen) 2123 2124SIGAR_DECLARE(int) sigar_fqdn_get(sigar_t *sigar, char *name, int namelen) 2125{ 2126 register int is_debug = SIGAR_LOG_IS_DEBUG(sigar); 2127 sigar_hostent_t data; 2128 struct hostent *p; 2129 char domain[SIGAR_FQDN_LEN + 1]; 2130#ifdef WIN32 2131 int status = sigar_wsa_init(sigar); 2132 2133 if (status != SIGAR_OK) { 2134 return status; 2135 } 2136#endif 2137 2138 if (gethostname(name, namelen - 1) != 0) { 2139 sigar_log_printf(sigar, SIGAR_LOG_ERROR, 2140 "[fqdn] gethostname failed: %s", 2141 sigar_strerror(sigar, errno)); 2142 return errno; 2143 } 2144 else { 2145 if (is_debug) { 2146 sigar_log_printf(sigar, SIGAR_LOG_DEBUG, 2147 "[fqdn] gethostname()=='%s'", 2148 name); 2149 } 2150 } 2151 2152 if (!(p = sigar_gethostbyname(name, &data))) { 2153 if (is_debug) { 2154 sigar_log_printf(sigar, SIGAR_LOG_DEBUG, 2155 "[fqdn] gethostbyname(%s) failed: %s", 2156 name, sigar_strerror(sigar, errno)); 2157 } 2158 2159 if (!IS_FQDN(name)) { 2160 fqdn_ip_get(sigar, name); 2161 } 2162 2163 return SIGAR_OK; 2164 } 2165 2166 if (IS_FQDN_MATCH(p->h_name, name)) { 2167 FQDN_SET(p->h_name); 2168 2169 sigar_log(sigar, SIGAR_LOG_DEBUG, 2170 "[fqdn] resolved using gethostbyname.h_name"); 2171 2172 return SIGAR_OK; 2173 } 2174 else { 2175 sigar_log_printf(sigar, SIGAR_LOG_DEBUG, 2176 "[fqdn] unresolved using gethostbyname.h_name"); 2177 } 2178 2179 if (p->h_aliases) { 2180 int i; 2181 2182 for (i=0; p->h_aliases[i]; i++) { 2183 if (IS_FQDN_MATCH(p->h_aliases[i], name)) { 2184 FQDN_SET(p->h_aliases[i]); 2185 2186 sigar_log(sigar, SIGAR_LOG_DEBUG, 2187 "[fqdn] resolved using gethostbyname.h_aliases"); 2188 2189 return SIGAR_OK; 2190 } 2191 else if (is_debug) { 2192 sigar_log_printf(sigar, SIGAR_LOG_DEBUG, 2193 "[fqdn] gethostbyname(%s).alias[%d]=='%s'", 2194 name, i, p->h_aliases[i]); 2195 } 2196 } 2197 } 2198 2199 sigar_log_printf(sigar, SIGAR_LOG_DEBUG, 2200 "[fqdn] unresolved using gethostbyname.h_aliases"); 2201 2202 if (p->h_addr_list) { 2203 int i,j; 2204 2205 for (i=0; p->h_addr_list[i]; i++) { 2206 char addr[SIGAR_INET6_ADDRSTRLEN]; 2207 struct in_addr *in = 2208 (struct in_addr *)p->h_addr_list[i]; 2209 2210 struct hostent *q = 2211 sigar_gethostbyaddr(p->h_addr_list[i], 2212 p->h_length, 2213 p->h_addrtype, 2214 &data); 2215 2216 if (is_debug) { 2217 sigar_inet_ntoa(sigar, in->s_addr, addr); 2218 } 2219 2220 if (!q) { 2221 if (is_debug) { 2222 sigar_log_printf(sigar, SIGAR_LOG_DEBUG, 2223 "[fqdn] gethostbyaddr(%s) failed: %s", 2224 addr, 2225 sigar_strerror(sigar, errno)); 2226 } 2227 continue; 2228 } 2229 2230 if (IS_FQDN_MATCH(q->h_name, name)) { 2231 FQDN_SET(q->h_name); 2232 2233 sigar_log(sigar, SIGAR_LOG_DEBUG, 2234 "[fqdn] resolved using gethostbyaddr.h_name"); 2235 2236 return SIGAR_OK; 2237 } 2238 else { 2239 if (is_debug) { 2240 sigar_log_printf(sigar, SIGAR_LOG_DEBUG, 2241 "[fqdn] gethostbyaddr(%s)=='%s'", 2242 addr, q->h_name); 2243 } 2244 2245 for (j=0; q->h_aliases[j]; j++) { 2246 if (IS_FQDN_MATCH(q->h_aliases[j], name)) { 2247 FQDN_SET(q->h_aliases[j]); 2248 2249 sigar_log(sigar, SIGAR_LOG_DEBUG, 2250 "[fqdn] resolved using " 2251 "gethostbyaddr.h_aliases"); 2252 2253 return SIGAR_OK; 2254 } 2255 else if (is_debug) { 2256 sigar_log_printf(sigar, SIGAR_LOG_DEBUG, 2257 "[fqdn] gethostbyaddr(%s).alias[%d]=='%s'", 2258 addr, j, q->h_aliases[j]); 2259 } 2260 } 2261 } 2262 } 2263 } 2264 2265 sigar_log(sigar, SIGAR_LOG_DEBUG, 2266 "[fqdn] unresolved using gethostbyname.h_addr_list"); 2267 2268#if !defined(WIN32) && !defined(NETWARE) 2269 if (!IS_FQDN(name) && /* e.g. aix gethostname is already fqdn */ 2270 (getdomainname(domain, sizeof(domain) - 1) == 0) && 2271 (domain[0] != '\0') && 2272 (domain[0] != '(')) /* linux default is "(none)" */ 2273 { 2274 /* sprintf(name, "%s.%s", name, domain); */ 2275 char *ptr = name; 2276 int len = strlen(name); 2277 ptr += len; 2278 *ptr++ = '.'; 2279 namelen -= (len+1); 2280 SIGAR_STRNCPY(ptr, domain, namelen); 2281 2282 sigar_log(sigar, SIGAR_LOG_DEBUG, 2283 "[fqdn] resolved using getdomainname"); 2284 } 2285 else { 2286 sigar_log(sigar, SIGAR_LOG_DEBUG, 2287 "[fqdn] getdomainname failed"); 2288 } 2289#endif 2290 2291 if (!IS_FQDN(name)) { 2292 fqdn_ip_get(sigar, name); 2293 } 2294 2295 return SIGAR_OK; 2296} 2297 2298#ifndef MAX_STRING_LEN 2299#define MAX_STRING_LEN 8192 2300#endif 2301 2302#ifdef WIN32 2303/* The windows version of getPasswordNative was lifted from apr */ 2304SIGAR_DECLARE(char *) sigar_password_get(const char *prompt) 2305{ 2306 static char password[MAX_STRING_LEN]; 2307 int n = 0; 2308 int ch; 2309 2310 fputs(prompt, stderr); 2311 fflush(stderr); 2312 2313 while ((ch = _getch()) != '\r') { 2314 if (ch == EOF) /* EOF */ { 2315 return NULL; 2316 } 2317 else if (ch == 0 || ch == 0xE0) { 2318 /* FN Keys (0 or E0) are a sentinal for a FN code */ 2319 ch = (ch << 4) | _getch(); 2320 /* Catch {DELETE}, {<--}, Num{DEL} and Num{<--} */ 2321 if ((ch == 0xE53 || ch == 0xE4B || ch == 0x053 || ch == 0x04b) && n) { 2322 password[--n] = '\0'; 2323 fputs("\b \b", stderr); 2324 fflush(stderr); 2325 } 2326 else { 2327 fputc('\a', stderr); 2328 fflush(stderr); 2329 } 2330 } 2331 else if ((ch == '\b' || ch == 127) && n) /* BS/DEL */ { 2332 password[--n] = '\0'; 2333 fputs("\b \b", stderr); 2334 fflush(stderr); 2335 } 2336 else if (ch == 3) /* CTRL+C */ { 2337 /* _getch() bypasses Ctrl+C but not Ctrl+Break detection! */ 2338 fputs("^C\n", stderr); 2339 fflush(stderr); 2340 exit(-1); 2341 } 2342 else if (ch == 26) /* CTRL+Z */ { 2343 fputs("^Z\n", stderr); 2344 fflush(stderr); 2345 return NULL; 2346 } 2347 else if (ch == 27) /* ESC */ { 2348 fputc('\n', stderr); 2349 fputs(prompt, stderr); 2350 fflush(stderr); 2351 n = 0; 2352 } 2353 else if ((n < sizeof(password) - 1) && !iscntrl(ch)) { 2354 password[n++] = ch; 2355 fputc(' ', stderr); 2356 fflush(stderr); 2357 } 2358 else { 2359 fputc('\a', stderr); 2360 fflush(stderr); 2361 } 2362 } 2363 2364 fputc('\n', stderr); 2365 fflush(stderr); 2366 password[n] = '\0'; 2367 2368 return password; 2369} 2370 2371#else 2372 2373/* linux/hpux/solaris getpass() prototype lives here */ 2374#include <unistd.h> 2375 2376#include <termios.h> 2377 2378/* from apr_getpass.c */ 2379 2380#if defined(SIGAR_HPUX) 2381# define getpass termios_getpass 2382#elif defined(SIGAR_SOLARIS) 2383# define getpass getpassphrase 2384#endif 2385 2386#ifdef SIGAR_HPUX 2387static char *termios_getpass(const char *prompt) 2388{ 2389 struct termios attr; 2390 static char password[MAX_STRING_LEN]; 2391 unsigned int n=0; 2392 2393 fputs(prompt, stderr); 2394 fflush(stderr); 2395 2396 if (tcgetattr(STDIN_FILENO, &attr) != 0) { 2397 return NULL; 2398 } 2399 2400 attr.c_lflag &= ~(ECHO); 2401 2402 if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &attr) != 0) { 2403 return NULL; 2404 } 2405 2406 while ((password[n] = getchar()) != '\n') { 2407 if (n < (sizeof(password) - 1) && 2408 (password[n] >= ' ') && 2409 (password[n] <= '~')) 2410 { 2411 n++; 2412 } 2413 else { 2414 fprintf(stderr, "\n"); 2415 fputs(prompt, stderr); 2416 fflush(stderr); 2417 n = 0; 2418 } 2419 } 2420 2421 password[n] = '\0'; 2422 printf("\n"); 2423 2424 if (n > (MAX_STRING_LEN - 1)) { 2425 password[MAX_STRING_LEN - 1] = '\0'; 2426 } 2427 2428 attr.c_lflag |= ECHO; 2429 tcsetattr(STDIN_FILENO, TCSANOW, &attr); 2430 2431 return (char *)&password; 2432} 2433#endif 2434 2435SIGAR_DECLARE(char *) sigar_password_get(const char *prompt) 2436{ 2437 char *buf = NULL; 2438 2439 /* the linux version of getpass prints the prompt to the tty; ok. 2440 * the solaris version prints the prompt to stderr; not ok. 2441 * so print the prompt to /dev/tty ourselves if possible (always should be) 2442 */ 2443 2444 FILE *tty = NULL; 2445 2446 if ((tty = fopen("/dev/tty", "w"))) { 2447 fprintf(tty, "%s", prompt); 2448 fflush(tty); 2449 2450 buf = getpass(tty ? "" : prompt); 2451 fclose(tty); 2452 } 2453 2454 return buf; 2455} 2456 2457#endif /* WIN32 */ 2458