sigar 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2428 @@
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
+
40
+ SIGAR_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
+
67
+ SIGAR_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 */
99
+ SIGAR_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 */
111
+ SIGAR_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
+
171
+ SIGAR_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
+
223
+ SIGAR_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
+
241
+ int 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
+
257
+ SIGAR_DECLARE(int)
258
+ sigar_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
+
286
+ int 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
+
295
+ int 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
+
305
+ SIGAR_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
+
316
+ SIGAR_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
+
337
+ int 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
+
346
+ int 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
+
356
+ SIGAR_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
+
372
+ SIGAR_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
+
385
+ int 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
+
394
+ int 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 */
405
+ static const char *fstype_names[] = {
406
+ "unknown", "none", "local", "remote", "ram", "cdrom", "swap"
407
+ };
408
+
409
+ static 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
+
473
+ void 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
+
490
+ SIGAR_DECLARE(int)
491
+ sigar_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
+
510
+ SIGAR_DECLARE(int)
511
+ sigar_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
+
542
+ int 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
+
551
+ int 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
+
561
+ SIGAR_DECLARE(int)
562
+ sigar_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
+
573
+ int 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
+
582
+ int 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
+
592
+ SIGAR_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
+
603
+ int 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
+
612
+ int 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
+
623
+ SIGAR_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
+
634
+ int 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
+
643
+ int 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
+
653
+ SIGAR_DECLARE(int)
654
+ sigar_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
+
670
+ int 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
+
679
+ int 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
+
690
+ SIGAR_DECLARE(int)
691
+ sigar_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
+ */
707
+ static 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
+
720
+ SIGAR_DECLARE(int)
721
+ sigar_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
+
745
+ static 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
+
764
+ SIGAR_DECLARE(int)
765
+ sigar_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
+
792
+ typedef struct {
793
+ sigar_net_stat_t *netstat;
794
+ sigar_net_connection_list_t *connlist;
795
+ } net_stat_getter_t;
796
+
797
+ static 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
+
836
+ SIGAR_DECLARE(int)
837
+ sigar_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
+
861
+ typedef struct {
862
+ sigar_net_stat_t *netstat;
863
+ sigar_net_address_t *address;
864
+ unsigned long port;
865
+ } net_stat_port_getter_t;
866
+
867
+ static 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
+
906
+ SIGAR_DECLARE(int)
907
+ sigar_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
+
940
+ static 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 */
953
+ int 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
+
967
+ int 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
+
976
+ int 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
+
986
+ SIGAR_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
+
997
+ int 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
+
1006
+ int 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
+
1016
+ SIGAR_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
+
1050
+ struct 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)
1061
+ static 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
1092
+ struct 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
1116
+ static 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
1158
+ static 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
+
1208
+ int sigar_who_list_get_win32(sigar_t *sigar,
1209
+ sigar_who_list_t *wholist);
1210
+
1211
+ SIGAR_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
+
1224
+ SIGAR_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)
1245
+ int sigar_resource_limit_get(sigar_t *sigar,
1246
+ sigar_resource_limit_t *rlimit)
1247
+ {
1248
+ return SIGAR_ENOTIMPL;
1249
+ }
1250
+
1251
+ int 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
1259
+ int 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
+
1276
+ static 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
+
1307
+ int 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
+
1378
+ typedef 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
+
1403
+ static 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
+
1423
+ int 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
+ #if !defined(WIN32) && !defined(NETWARE) && !defined(DARWIN) && \
1462
+ !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
1463
+
1464
+ /* XXX: prolly will be moving these stuffs into os_net.c */
1465
+ #include <sys/ioctl.h>
1466
+ #include <net/if.h>
1467
+
1468
+ #ifndef SIOCGIFCONF
1469
+ #include <sys/sockio.h>
1470
+ #endif
1471
+
1472
+ #if defined(_AIX) || defined(__osf__) /* good buddies */
1473
+
1474
+ #include <net/if_dl.h>
1475
+
1476
+ static void hwaddr_aix_lookup(sigar_t *sigar, sigar_net_interface_config_t *ifconfig)
1477
+ {
1478
+ char *ent, *end;
1479
+ struct ifreq *ifr;
1480
+
1481
+ /* XXX: assumes sigar_net_interface_list_get has been called */
1482
+ end = sigar->ifconf_buf + sigar->ifconf_len;
1483
+
1484
+ for (ent = sigar->ifconf_buf;
1485
+ ent < end;
1486
+ ent += sizeof(*ifr))
1487
+ {
1488
+ ifr = (struct ifreq *)ent;
1489
+
1490
+ if (ifr->ifr_addr.sa_family != AF_LINK) {
1491
+ continue;
1492
+ }
1493
+
1494
+ if (strEQ(ifr->ifr_name, ifconfig->name)) {
1495
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
1496
+
1497
+ sigar_net_address_mac_set(ifconfig->hwaddr,
1498
+ LLADDR(sdl),
1499
+ sdl->sdl_alen);
1500
+ return;
1501
+ }
1502
+ }
1503
+
1504
+ sigar_hwaddr_set_null(ifconfig);
1505
+ }
1506
+
1507
+ #elif !defined(SIOCGIFHWADDR)
1508
+
1509
+ #include <net/if_arp.h>
1510
+
1511
+ static void hwaddr_arp_lookup(sigar_net_interface_config_t *ifconfig, int sock)
1512
+ {
1513
+ struct arpreq areq;
1514
+ struct sockaddr_in *sa;
1515
+
1516
+ memset(&areq, 0, sizeof(areq));
1517
+ sa = (struct sockaddr_in *)&areq.arp_pa;
1518
+ sa->sin_family = AF_INET;
1519
+ sa->sin_addr.s_addr = ifconfig->address.addr.in;
1520
+
1521
+ if (ioctl(sock, SIOCGARP, &areq) < 0) {
1522
+ /* ho-hum */
1523
+ sigar_hwaddr_set_null(ifconfig);
1524
+ }
1525
+ else {
1526
+ sigar_net_address_mac_set(ifconfig->hwaddr,
1527
+ areq.arp_ha.sa_data,
1528
+ SIGAR_IFHWADDRLEN);
1529
+ }
1530
+ }
1531
+
1532
+ #endif
1533
+
1534
+ #ifdef __linux__
1535
+
1536
+ #include <net/if_arp.h>
1537
+
1538
+ #ifndef ARPHRD_CISCO /* not in 2.2 kernel headers */
1539
+ #define ARPHRD_CISCO 513 /* Cisco HDLC. */
1540
+ #endif
1541
+
1542
+ static void get_interface_type(sigar_net_interface_config_t *ifconfig,
1543
+ int family)
1544
+ {
1545
+ char *type;
1546
+
1547
+ switch (family) {
1548
+ case ARPHRD_SLIP:
1549
+ type = SIGAR_NIC_SLIP;
1550
+ break;
1551
+ case ARPHRD_CSLIP:
1552
+ type = SIGAR_NIC_CSLIP;
1553
+ break;
1554
+ case ARPHRD_SLIP6:
1555
+ type = SIGAR_NIC_SLIP6;
1556
+ break;
1557
+ case ARPHRD_CSLIP6:
1558
+ type = SIGAR_NIC_CSLIP6;
1559
+ break;
1560
+ case ARPHRD_ADAPT:
1561
+ type = SIGAR_NIC_ADAPTIVE;
1562
+ break;
1563
+ case ARPHRD_ETHER:
1564
+ type = SIGAR_NIC_ETHERNET;
1565
+ break;
1566
+ case ARPHRD_ASH:
1567
+ type = SIGAR_NIC_ASH;
1568
+ break;
1569
+ case ARPHRD_FDDI:
1570
+ type = SIGAR_NIC_FDDI;
1571
+ break;
1572
+ case ARPHRD_HIPPI:
1573
+ type = SIGAR_NIC_HIPPI;
1574
+ break;
1575
+ case ARPHRD_AX25:
1576
+ type = SIGAR_NIC_AX25;
1577
+ break;
1578
+ case ARPHRD_ROSE:
1579
+ type = SIGAR_NIC_ROSE;
1580
+ break;
1581
+ case ARPHRD_NETROM:
1582
+ type = SIGAR_NIC_NETROM;
1583
+ break;
1584
+ case ARPHRD_X25:
1585
+ type = SIGAR_NIC_X25;
1586
+ break;
1587
+ case ARPHRD_TUNNEL:
1588
+ type = SIGAR_NIC_TUNNEL;
1589
+ break;
1590
+ case ARPHRD_PPP:
1591
+ type = SIGAR_NIC_PPP;
1592
+ break;
1593
+ case ARPHRD_CISCO:
1594
+ type = SIGAR_NIC_HDLC;
1595
+ break;
1596
+ case ARPHRD_LAPB:
1597
+ type = SIGAR_NIC_LAPB;
1598
+ break;
1599
+ case ARPHRD_ARCNET:
1600
+ type = SIGAR_NIC_ARCNET;
1601
+ break;
1602
+ case ARPHRD_DLCI:
1603
+ type = SIGAR_NIC_DLCI;
1604
+ break;
1605
+ case ARPHRD_FRAD:
1606
+ type = SIGAR_NIC_FRAD;
1607
+ break;
1608
+ case ARPHRD_SIT:
1609
+ type = SIGAR_NIC_SIT;
1610
+ break;
1611
+ case ARPHRD_IRDA:
1612
+ type = SIGAR_NIC_IRDA;
1613
+ break;
1614
+ case ARPHRD_ECONET:
1615
+ type = SIGAR_NIC_EC;
1616
+ break;
1617
+ default:
1618
+ type = SIGAR_NIC_UNSPEC;
1619
+ break;
1620
+ }
1621
+
1622
+ SIGAR_SSTRCPY(ifconfig->type, type);
1623
+ }
1624
+
1625
+ #endif
1626
+
1627
+ int sigar_net_interface_config_get(sigar_t *sigar, const char *name,
1628
+ sigar_net_interface_config_t *ifconfig)
1629
+ {
1630
+ int sock;
1631
+ struct ifreq ifr;
1632
+
1633
+ if (!name) {
1634
+ return sigar_net_interface_config_primary_get(sigar, ifconfig);
1635
+ }
1636
+
1637
+ SIGAR_ZERO(ifconfig);
1638
+
1639
+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1640
+ return errno;
1641
+ }
1642
+
1643
+ SIGAR_SSTRCPY(ifconfig->name, name);
1644
+ SIGAR_SSTRCPY(ifr.ifr_name, name);
1645
+
1646
+ #define ifr_s_addr(ifr) \
1647
+ ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr
1648
+
1649
+ if (!ioctl(sock, SIOCGIFADDR, &ifr)) {
1650
+ sigar_net_address_set(ifconfig->address,
1651
+ ifr_s_addr(ifr));
1652
+ }
1653
+
1654
+ if (!ioctl(sock, SIOCGIFNETMASK, &ifr)) {
1655
+ sigar_net_address_set(ifconfig->netmask,
1656
+ ifr_s_addr(ifr));
1657
+ }
1658
+
1659
+ if (!ioctl(sock, SIOCGIFFLAGS, &ifr)) {
1660
+ sigar_uint64_t flags = ifr.ifr_flags;
1661
+ #ifdef __linux__
1662
+ # ifndef IFF_DYNAMIC
1663
+ # define IFF_DYNAMIC 0x8000 /* not in 2.2 kernel */
1664
+ # endif /* IFF_DYNAMIC */
1665
+ int is_mcast = flags & IFF_MULTICAST;
1666
+ int is_slave = flags & IFF_SLAVE;
1667
+ int is_master = flags & IFF_MASTER;
1668
+ int is_dynamic = flags & IFF_DYNAMIC;
1669
+ /*
1670
+ * XXX: should just define SIGAR_IFF_*
1671
+ * and test IFF_* bits on given platform.
1672
+ * this is the only diff between solaris/hpux/linux
1673
+ * for the flags we care about.
1674
+ *
1675
+ */
1676
+ flags &= ~(IFF_MULTICAST|IFF_SLAVE|IFF_MASTER);
1677
+ if (is_mcast) {
1678
+ flags |= SIGAR_IFF_MULTICAST;
1679
+ }
1680
+ if (is_slave) {
1681
+ flags |= SIGAR_IFF_SLAVE;
1682
+ }
1683
+ if (is_master) {
1684
+ flags |= SIGAR_IFF_MASTER;
1685
+ }
1686
+ if (is_dynamic) {
1687
+ flags |= SIGAR_IFF_DYNAMIC;
1688
+ }
1689
+ #endif
1690
+ ifconfig->flags = flags;
1691
+ }
1692
+ else {
1693
+ /* should always be able to get flags for existing device */
1694
+ /* other ioctls may fail if device is not enabled: ok */
1695
+ close(sock);
1696
+ return errno;
1697
+ }
1698
+
1699
+ if (ifconfig->flags & IFF_LOOPBACK) {
1700
+ sigar_net_address_set(ifconfig->destination,
1701
+ ifconfig->address.addr.in);
1702
+ sigar_net_address_set(ifconfig->broadcast, 0);
1703
+ sigar_hwaddr_set_null(ifconfig);
1704
+ SIGAR_SSTRCPY(ifconfig->type,
1705
+ SIGAR_NIC_LOOPBACK);
1706
+ }
1707
+ else {
1708
+ if (!ioctl(sock, SIOCGIFDSTADDR, &ifr)) {
1709
+ sigar_net_address_set(ifconfig->destination,
1710
+ ifr_s_addr(ifr));
1711
+ }
1712
+
1713
+ if (!ioctl(sock, SIOCGIFBRDADDR, &ifr)) {
1714
+ sigar_net_address_set(ifconfig->broadcast,
1715
+ ifr_s_addr(ifr));
1716
+ }
1717
+
1718
+ #if defined(SIOCGIFHWADDR)
1719
+ if (!ioctl(sock, SIOCGIFHWADDR, &ifr)) {
1720
+ get_interface_type(ifconfig,
1721
+ ifr.ifr_hwaddr.sa_family);
1722
+ sigar_net_address_mac_set(ifconfig->hwaddr,
1723
+ ifr.ifr_hwaddr.sa_data,
1724
+ IFHWADDRLEN);
1725
+ }
1726
+ #elif defined(_AIX) || defined(__osf__)
1727
+ hwaddr_aix_lookup(sigar, ifconfig);
1728
+ SIGAR_SSTRCPY(ifconfig->type,
1729
+ SIGAR_NIC_ETHERNET);
1730
+ #else
1731
+ hwaddr_arp_lookup(ifconfig, sock);
1732
+ SIGAR_SSTRCPY(ifconfig->type,
1733
+ SIGAR_NIC_ETHERNET);
1734
+ #endif
1735
+ }
1736
+
1737
+ #if defined(SIOCGLIFMTU) && !defined(__hpux)
1738
+ {
1739
+ struct lifreq lifr;
1740
+ SIGAR_SSTRCPY(lifr.lifr_name, name);
1741
+ if(!ioctl(sock, SIOCGLIFMTU, &lifr)) {
1742
+ ifconfig->mtu = lifr.lifr_mtu;
1743
+ }
1744
+ }
1745
+ #elif defined(SIOCGIFMTU)
1746
+ if (!ioctl(sock, SIOCGIFMTU, &ifr)) {
1747
+ # if defined(__hpux)
1748
+ ifconfig->mtu = ifr.ifr_metric;
1749
+ # else
1750
+ ifconfig->mtu = ifr.ifr_mtu;
1751
+ #endif
1752
+ }
1753
+ #else
1754
+ ifconfig->mtu = 0; /*XXX*/
1755
+ #endif
1756
+
1757
+ if (!ioctl(sock, SIOCGIFMETRIC, &ifr)) {
1758
+ ifconfig->metric = ifr.ifr_metric ? ifr.ifr_metric : 1;
1759
+ }
1760
+
1761
+ #if defined(SIOCGIFTXQLEN)
1762
+ if (!ioctl(sock, SIOCGIFTXQLEN, &ifr)) {
1763
+ ifconfig->tx_queue_len = ifr.ifr_qlen;
1764
+ }
1765
+ else {
1766
+ ifconfig->tx_queue_len = -1; /* net-tools behaviour */
1767
+ }
1768
+ #else
1769
+ ifconfig->tx_queue_len = -1;
1770
+ #endif
1771
+
1772
+ close(sock);
1773
+
1774
+ /* XXX can we get a better description like win32? */
1775
+ SIGAR_SSTRCPY(ifconfig->description,
1776
+ ifconfig->name);
1777
+
1778
+ sigar_net_interface_ipv6_config_init(ifconfig);
1779
+ sigar_net_interface_ipv6_config_get(sigar, name, ifconfig);
1780
+
1781
+ return SIGAR_OK;
1782
+ }
1783
+
1784
+ #ifdef _AIX
1785
+ # define MY_SIOCGIFCONF CSIOCGIFCONF
1786
+ #else
1787
+ # define MY_SIOCGIFCONF SIOCGIFCONF
1788
+ #endif
1789
+
1790
+ #ifdef __osf__
1791
+ static int sigar_netif_configured(sigar_t *sigar, char *name)
1792
+ {
1793
+ int status;
1794
+ sigar_net_interface_config_t ifconfig;
1795
+
1796
+ status = sigar_net_interface_config_get(sigar, name, &ifconfig);
1797
+
1798
+ return status == SIGAR_OK;
1799
+ }
1800
+ #endif
1801
+
1802
+ #ifdef __linux__
1803
+ static SIGAR_INLINE int has_interface(sigar_net_interface_list_t *iflist,
1804
+ char *name)
1805
+ {
1806
+ register int i;
1807
+ register int num = iflist->number;
1808
+ register char **data = iflist->data;
1809
+ for (i=0; i<num; i++) {
1810
+ if (strEQ(name, data[i])) {
1811
+ return 1;
1812
+ }
1813
+ }
1814
+ return 0;
1815
+ }
1816
+
1817
+ static int proc_net_interface_list_get(sigar_t *sigar,
1818
+ sigar_net_interface_list_t *iflist)
1819
+ {
1820
+ /* certain interfaces such as VMware vmnic
1821
+ * are not returned by ioctl(SIOCGIFCONF).
1822
+ * check /proc/net/dev for any ioctl missed.
1823
+ */
1824
+ char buffer[BUFSIZ];
1825
+ FILE *fp = fopen("/proc/net/dev", "r");
1826
+
1827
+ if (!fp) {
1828
+ return errno;
1829
+ }
1830
+
1831
+ /* skip header */
1832
+ fgets(buffer, sizeof(buffer), fp);
1833
+ fgets(buffer, sizeof(buffer), fp);
1834
+
1835
+ while (fgets(buffer, sizeof(buffer), fp)) {
1836
+ char *ptr, *dev;
1837
+
1838
+ dev = buffer;
1839
+ while (isspace(*dev)) {
1840
+ dev++;
1841
+ }
1842
+
1843
+ if (!(ptr = strchr(dev, ':'))) {
1844
+ continue;
1845
+ }
1846
+
1847
+ *ptr++ = 0;
1848
+
1849
+ if (has_interface(iflist, dev)) {
1850
+ continue;
1851
+ }
1852
+
1853
+ SIGAR_NET_IFLIST_GROW(iflist);
1854
+
1855
+ iflist->data[iflist->number++] =
1856
+ sigar_strdup(dev);
1857
+ }
1858
+
1859
+ fclose(fp);
1860
+
1861
+ return SIGAR_OK;
1862
+ }
1863
+ #endif
1864
+
1865
+ int sigar_net_interface_list_get(sigar_t *sigar,
1866
+ sigar_net_interface_list_t *iflist)
1867
+ {
1868
+ int n, lastlen=0;
1869
+ struct ifreq *ifr;
1870
+ struct ifconf ifc;
1871
+ int sock = socket(AF_INET, SOCK_DGRAM, 0);
1872
+
1873
+ if (sock < 0) {
1874
+ return errno;
1875
+ }
1876
+
1877
+ for (;;) {
1878
+ if (!sigar->ifconf_buf || lastlen) {
1879
+ sigar->ifconf_len += sizeof(struct ifreq) * SIGAR_NET_IFLIST_MAX;
1880
+ sigar->ifconf_buf = realloc(sigar->ifconf_buf, sigar->ifconf_len);
1881
+ }
1882
+
1883
+ ifc.ifc_len = sigar->ifconf_len;
1884
+ ifc.ifc_buf = sigar->ifconf_buf;
1885
+
1886
+ if (ioctl(sock, MY_SIOCGIFCONF, &ifc) < 0) {
1887
+ /* EINVAL should mean num_interfaces > ifc.ifc_len */
1888
+ if ((errno != EINVAL) ||
1889
+ (lastlen == ifc.ifc_len))
1890
+ {
1891
+ free(ifc.ifc_buf);
1892
+ return errno;
1893
+ }
1894
+ }
1895
+
1896
+ if (ifc.ifc_len < sigar->ifconf_len) {
1897
+ break; /* got em all */
1898
+ }
1899
+
1900
+ if (ifc.ifc_len != lastlen) {
1901
+ /* might be more */
1902
+ lastlen = ifc.ifc_len;
1903
+ continue;
1904
+ }
1905
+
1906
+ break;
1907
+ }
1908
+
1909
+ close(sock);
1910
+
1911
+ iflist->number = 0;
1912
+ iflist->size = ifc.ifc_len;
1913
+ iflist->data = malloc(sizeof(*(iflist->data)) *
1914
+ iflist->size);
1915
+
1916
+ ifr = ifc.ifc_req;
1917
+ for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq), ifr++) {
1918
+ #if defined(_AIX) || defined(__osf__) /* pass the bourbon */
1919
+ if (ifr->ifr_addr.sa_family != AF_LINK) {
1920
+ /* XXX: dunno if this is right.
1921
+ * otherwise end up with two 'en0' and three 'lo0'
1922
+ * with the same ip address.
1923
+ */
1924
+ continue;
1925
+ }
1926
+ # ifdef __osf__
1927
+ /* weed out "sl0", "tun0" and the like */
1928
+ /* XXX must be a better way to check this */
1929
+ if (!sigar_netif_configured(sigar, ifr->ifr_name)) {
1930
+ continue;
1931
+ }
1932
+ # endif
1933
+ #endif
1934
+ iflist->data[iflist->number++] =
1935
+ sigar_strdup(ifr->ifr_name);
1936
+ }
1937
+
1938
+ #ifdef __linux__
1939
+ proc_net_interface_list_get(sigar, iflist);
1940
+ #endif
1941
+
1942
+ return SIGAR_OK;
1943
+ }
1944
+
1945
+ #endif /* WIN32 */
1946
+
1947
+ SIGAR_DECLARE(int)
1948
+ sigar_net_interface_config_primary_get(sigar_t *sigar,
1949
+ sigar_net_interface_config_t *ifconfig)
1950
+ {
1951
+ int i, status, found=0;
1952
+ sigar_net_interface_list_t iflist;
1953
+ sigar_net_interface_config_t possible_config;
1954
+
1955
+ possible_config.flags = 0;
1956
+
1957
+ if ((status = sigar_net_interface_list_get(sigar, &iflist)) != SIGAR_OK) {
1958
+ return status;
1959
+ }
1960
+
1961
+ for (i=0; i<iflist.number; i++) {
1962
+ status = sigar_net_interface_config_get(sigar,
1963
+ iflist.data[i], ifconfig);
1964
+
1965
+ if ((status != SIGAR_OK) ||
1966
+ (ifconfig->flags & SIGAR_IFF_LOOPBACK) ||
1967
+ !ifconfig->hwaddr.addr.in) /* no mac address */
1968
+ {
1969
+ continue;
1970
+ }
1971
+
1972
+ if (!possible_config.flags) {
1973
+ /* save for later for use if we're not connected to the net
1974
+ * or all interfaces are aliases (e.g. solaris zone)
1975
+ */
1976
+ memcpy(&possible_config, ifconfig, sizeof(*ifconfig));
1977
+ }
1978
+ if (!ifconfig->address.addr.in) {
1979
+ continue; /* no ip address */
1980
+ }
1981
+ if (strchr(iflist.data[i], ':')) {
1982
+ continue; /* alias */
1983
+ }
1984
+
1985
+ found = 1;
1986
+ break;
1987
+ }
1988
+
1989
+ sigar_net_interface_list_destroy(sigar, &iflist);
1990
+
1991
+ if (found) {
1992
+ return SIGAR_OK;
1993
+ }
1994
+ else if (possible_config.flags) {
1995
+ memcpy(ifconfig, &possible_config, sizeof(*ifconfig));
1996
+ return SIGAR_OK;
1997
+ }
1998
+ else {
1999
+ return SIGAR_ENXIO;
2000
+ }
2001
+ }
2002
+
2003
+ static int fqdn_ip_get(sigar_t *sigar, char *name)
2004
+ {
2005
+ sigar_net_interface_config_t ifconfig;
2006
+ int status;
2007
+
2008
+ status = sigar_net_interface_config_primary_get(sigar, &ifconfig);
2009
+
2010
+ if (status != SIGAR_OK) {
2011
+ return status;
2012
+ }
2013
+ if (!ifconfig.address.addr.in) {
2014
+ return SIGAR_ENXIO;
2015
+ }
2016
+
2017
+ sigar_net_address_to_string(sigar, &ifconfig.address, name);
2018
+
2019
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2020
+ "[fqdn] using ip address '%s' for fqdn",
2021
+ name);
2022
+
2023
+ return SIGAR_OK;
2024
+ }
2025
+
2026
+ struct hostent *sigar_gethostbyname(const char *name,
2027
+ sigar_hostent_t *data)
2028
+ {
2029
+ struct hostent *hp = NULL;
2030
+
2031
+ #if defined(__linux__)
2032
+ gethostbyname_r(name, &data->hs,
2033
+ data->buffer, sizeof(data->buffer),
2034
+ &hp, &data->error);
2035
+ #elif defined(__sun)
2036
+ hp = gethostbyname_r(name, &data->hs,
2037
+ data->buffer, sizeof(data->buffer),
2038
+ &data->error);
2039
+ #elif defined(SIGAR_HAS_HOSTENT_DATA)
2040
+ if (gethostbyname_r(name, &data->hs, &data->hd) == 0) {
2041
+ hp = &data->hs;
2042
+ }
2043
+ else {
2044
+ data->error = h_errno;
2045
+ }
2046
+ #else
2047
+ hp = gethostbyname(name);
2048
+ #endif
2049
+
2050
+ return hp;
2051
+ }
2052
+
2053
+ static struct hostent *sigar_gethostbyaddr(const char *addr,
2054
+ int len, int type,
2055
+ sigar_hostent_t *data)
2056
+ {
2057
+ struct hostent *hp = NULL;
2058
+
2059
+ #if defined(__linux__)
2060
+ gethostbyaddr_r(addr, len, type,
2061
+ &data->hs,
2062
+ data->buffer, sizeof(data->buffer),
2063
+ &hp, &data->error);
2064
+ #elif defined(__sun)
2065
+ hp = gethostbyaddr_r(addr, len, type,
2066
+ &data->hs,
2067
+ data->buffer, sizeof(data->buffer),
2068
+ &data->error);
2069
+ #elif defined(SIGAR_HAS_HOSTENT_DATA)
2070
+ if (gethostbyaddr_r((char *)addr, len, type,
2071
+ &data->hs, &data->hd) == 0)
2072
+ {
2073
+ hp = &data->hs;
2074
+ }
2075
+ else {
2076
+ data->error = h_errno;
2077
+ }
2078
+ #else
2079
+ if (!(hp = gethostbyaddr(addr, len, type))) {
2080
+ data->error = h_errno;
2081
+ }
2082
+ #endif
2083
+
2084
+ return hp;
2085
+ }
2086
+ #define IS_FQDN(name) \
2087
+ (name && strchr(name, '.'))
2088
+
2089
+ #define IS_FQDN_MATCH(lookup, name) \
2090
+ (IS_FQDN(lookup) && strnEQ(lookup, name, strlen(name)))
2091
+
2092
+ #define FQDN_SET(fqdn) \
2093
+ SIGAR_STRNCPY(name, fqdn, namelen)
2094
+
2095
+ SIGAR_DECLARE(int) sigar_fqdn_get(sigar_t *sigar, char *name, int namelen)
2096
+ {
2097
+ register int is_debug = SIGAR_LOG_IS_DEBUG(sigar);
2098
+ sigar_hostent_t data;
2099
+ struct hostent *p;
2100
+ char domain[SIGAR_FQDN_LEN + 1];
2101
+ #ifdef WIN32
2102
+ int status = sigar_wsa_init(sigar);
2103
+
2104
+ if (status != SIGAR_OK) {
2105
+ return status;
2106
+ }
2107
+ #endif
2108
+
2109
+ if (gethostname(name, namelen - 1) != 0) {
2110
+ sigar_log_printf(sigar, SIGAR_LOG_ERROR,
2111
+ "[fqdn] gethostname failed: %s",
2112
+ sigar_strerror(sigar, errno));
2113
+ return errno;
2114
+ }
2115
+ else {
2116
+ if (is_debug) {
2117
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2118
+ "[fqdn] gethostname()=='%s'",
2119
+ name);
2120
+ }
2121
+ }
2122
+
2123
+ if (!(p = sigar_gethostbyname(name, &data))) {
2124
+ if (is_debug) {
2125
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2126
+ "[fqdn] gethostbyname(%s) failed: %s",
2127
+ name, sigar_strerror(sigar, errno));
2128
+ }
2129
+
2130
+ if (!IS_FQDN(name)) {
2131
+ fqdn_ip_get(sigar, name);
2132
+ }
2133
+
2134
+ return SIGAR_OK;
2135
+ }
2136
+
2137
+ if (IS_FQDN_MATCH(p->h_name, name)) {
2138
+ FQDN_SET(p->h_name);
2139
+
2140
+ sigar_log(sigar, SIGAR_LOG_DEBUG,
2141
+ "[fqdn] resolved using gethostbyname.h_name");
2142
+
2143
+ return SIGAR_OK;
2144
+ }
2145
+ else {
2146
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2147
+ "[fqdn] unresolved using gethostbyname.h_name");
2148
+ }
2149
+
2150
+ if (p->h_aliases) {
2151
+ int i;
2152
+
2153
+ for (i=0; p->h_aliases[i]; i++) {
2154
+ if (IS_FQDN_MATCH(p->h_aliases[i], name)) {
2155
+ FQDN_SET(p->h_aliases[i]);
2156
+
2157
+ sigar_log(sigar, SIGAR_LOG_DEBUG,
2158
+ "[fqdn] resolved using gethostbyname.h_aliases");
2159
+
2160
+ return SIGAR_OK;
2161
+ }
2162
+ else if (is_debug) {
2163
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2164
+ "[fqdn] gethostbyname(%s).alias[%d]=='%s'",
2165
+ name, i, p->h_aliases[i]);
2166
+ }
2167
+ }
2168
+ }
2169
+
2170
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2171
+ "[fqdn] unresolved using gethostbyname.h_aliases");
2172
+
2173
+ if (p->h_addr_list) {
2174
+ int i,j;
2175
+
2176
+ for (i=0; p->h_addr_list[i]; i++) {
2177
+ char addr[SIGAR_INET6_ADDRSTRLEN];
2178
+ struct in_addr *in =
2179
+ (struct in_addr *)p->h_addr_list[i];
2180
+
2181
+ struct hostent *q =
2182
+ sigar_gethostbyaddr(p->h_addr_list[i],
2183
+ p->h_length,
2184
+ p->h_addrtype,
2185
+ &data);
2186
+
2187
+ if (is_debug) {
2188
+ sigar_inet_ntoa(sigar, in->s_addr, addr);
2189
+ }
2190
+
2191
+ if (!q) {
2192
+ if (is_debug) {
2193
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2194
+ "[fqdn] gethostbyaddr(%s) failed: %s",
2195
+ addr,
2196
+ sigar_strerror(sigar, errno));
2197
+ }
2198
+ continue;
2199
+ }
2200
+
2201
+ if (IS_FQDN_MATCH(q->h_name, name)) {
2202
+ FQDN_SET(q->h_name);
2203
+
2204
+ sigar_log(sigar, SIGAR_LOG_DEBUG,
2205
+ "[fqdn] resolved using gethostbyaddr.h_name");
2206
+
2207
+ return SIGAR_OK;
2208
+ }
2209
+ else {
2210
+ if (is_debug) {
2211
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2212
+ "[fqdn] gethostbyaddr(%s)=='%s'",
2213
+ addr, q->h_name);
2214
+ }
2215
+
2216
+ for (j=0; q->h_aliases[j]; j++) {
2217
+ if (IS_FQDN_MATCH(q->h_aliases[j], name)) {
2218
+ FQDN_SET(q->h_aliases[j]);
2219
+
2220
+ sigar_log(sigar, SIGAR_LOG_DEBUG,
2221
+ "[fqdn] resolved using "
2222
+ "gethostbyaddr.h_aliases");
2223
+
2224
+ return SIGAR_OK;
2225
+ }
2226
+ else if (is_debug) {
2227
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
2228
+ "[fqdn] gethostbyaddr(%s).alias[%d]=='%s'",
2229
+ addr, j, q->h_aliases[j]);
2230
+ }
2231
+ }
2232
+ }
2233
+ }
2234
+ }
2235
+
2236
+ sigar_log(sigar, SIGAR_LOG_DEBUG,
2237
+ "[fqdn] unresolved using gethostbyname.h_addr_list");
2238
+
2239
+ #if !defined(WIN32) && !defined(NETWARE)
2240
+ if (!IS_FQDN(name) && /* e.g. aix gethostname is already fqdn */
2241
+ (getdomainname(domain, sizeof(domain) - 1) == 0) &&
2242
+ (domain[0] != '\0') &&
2243
+ (domain[0] != '(')) /* linux default is "(none)" */
2244
+ {
2245
+ /* sprintf(name, "%s.%s", name, domain); */
2246
+ char *ptr = name;
2247
+ int len = strlen(name);
2248
+ ptr += len;
2249
+ *ptr++ = '.';
2250
+ namelen -= (len+1);
2251
+ SIGAR_STRNCPY(ptr, domain, namelen);
2252
+
2253
+ sigar_log(sigar, SIGAR_LOG_DEBUG,
2254
+ "[fqdn] resolved using getdomainname");
2255
+ }
2256
+ else {
2257
+ sigar_log(sigar, SIGAR_LOG_DEBUG,
2258
+ "[fqdn] getdomainname failed");
2259
+ }
2260
+ #endif
2261
+
2262
+ if (!IS_FQDN(name)) {
2263
+ fqdn_ip_get(sigar, name);
2264
+ }
2265
+
2266
+ return SIGAR_OK;
2267
+ }
2268
+
2269
+ #ifndef MAX_STRING_LEN
2270
+ #define MAX_STRING_LEN 8192
2271
+ #endif
2272
+
2273
+ #ifdef WIN32
2274
+ /* The windows version of getPasswordNative was lifted from apr */
2275
+ SIGAR_DECLARE(char *) sigar_password_get(const char *prompt)
2276
+ {
2277
+ static char password[MAX_STRING_LEN];
2278
+ int n = 0;
2279
+ int ch;
2280
+
2281
+ fputs(prompt, stderr);
2282
+ fflush(stderr);
2283
+
2284
+ while ((ch = _getch()) != '\r') {
2285
+ if (ch == EOF) /* EOF */ {
2286
+ return NULL;
2287
+ }
2288
+ else if (ch == 0 || ch == 0xE0) {
2289
+ /* FN Keys (0 or E0) are a sentinal for a FN code */
2290
+ ch = (ch << 4) | _getch();
2291
+ /* Catch {DELETE}, {<--}, Num{DEL} and Num{<--} */
2292
+ if ((ch == 0xE53 || ch == 0xE4B || ch == 0x053 || ch == 0x04b) && n) {
2293
+ password[--n] = '\0';
2294
+ fputs("\b \b", stderr);
2295
+ fflush(stderr);
2296
+ }
2297
+ else {
2298
+ fputc('\a', stderr);
2299
+ fflush(stderr);
2300
+ }
2301
+ }
2302
+ else if ((ch == '\b' || ch == 127) && n) /* BS/DEL */ {
2303
+ password[--n] = '\0';
2304
+ fputs("\b \b", stderr);
2305
+ fflush(stderr);
2306
+ }
2307
+ else if (ch == 3) /* CTRL+C */ {
2308
+ /* _getch() bypasses Ctrl+C but not Ctrl+Break detection! */
2309
+ fputs("^C\n", stderr);
2310
+ fflush(stderr);
2311
+ exit(-1);
2312
+ }
2313
+ else if (ch == 26) /* CTRL+Z */ {
2314
+ fputs("^Z\n", stderr);
2315
+ fflush(stderr);
2316
+ return NULL;
2317
+ }
2318
+ else if (ch == 27) /* ESC */ {
2319
+ fputc('\n', stderr);
2320
+ fputs(prompt, stderr);
2321
+ fflush(stderr);
2322
+ n = 0;
2323
+ }
2324
+ else if ((n < sizeof(password) - 1) && !iscntrl(ch)) {
2325
+ password[n++] = ch;
2326
+ fputc(' ', stderr);
2327
+ fflush(stderr);
2328
+ }
2329
+ else {
2330
+ fputc('\a', stderr);
2331
+ fflush(stderr);
2332
+ }
2333
+ }
2334
+
2335
+ fputc('\n', stderr);
2336
+ fflush(stderr);
2337
+ password[n] = '\0';
2338
+
2339
+ return password;
2340
+ }
2341
+
2342
+ #else
2343
+
2344
+ /* linux/hpux/solaris getpass() prototype lives here */
2345
+ #include <unistd.h>
2346
+
2347
+ #include <termios.h>
2348
+
2349
+ /* from apr_getpass.c */
2350
+
2351
+ #if defined(SIGAR_HPUX)
2352
+ # define getpass termios_getpass
2353
+ #elif defined(SIGAR_SOLARIS)
2354
+ # define getpass getpassphrase
2355
+ #endif
2356
+
2357
+ #ifdef SIGAR_HPUX
2358
+ static char *termios_getpass(const char *prompt)
2359
+ {
2360
+ struct termios attr;
2361
+ static char password[MAX_STRING_LEN];
2362
+ unsigned int n=0;
2363
+
2364
+ fputs(prompt, stderr);
2365
+ fflush(stderr);
2366
+
2367
+ if (tcgetattr(STDIN_FILENO, &attr) != 0) {
2368
+ return NULL;
2369
+ }
2370
+
2371
+ attr.c_lflag &= ~(ECHO);
2372
+
2373
+ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &attr) != 0) {
2374
+ return NULL;
2375
+ }
2376
+
2377
+ while ((password[n] = getchar()) != '\n') {
2378
+ if (n < (sizeof(password) - 1) &&
2379
+ (password[n] >= ' ') &&
2380
+ (password[n] <= '~'))
2381
+ {
2382
+ n++;
2383
+ }
2384
+ else {
2385
+ fprintf(stderr, "\n");
2386
+ fputs(prompt, stderr);
2387
+ fflush(stderr);
2388
+ n = 0;
2389
+ }
2390
+ }
2391
+
2392
+ password[n] = '\0';
2393
+ printf("\n");
2394
+
2395
+ if (n > (MAX_STRING_LEN - 1)) {
2396
+ password[MAX_STRING_LEN - 1] = '\0';
2397
+ }
2398
+
2399
+ attr.c_lflag |= ECHO;
2400
+ tcsetattr(STDIN_FILENO, TCSANOW, &attr);
2401
+
2402
+ return (char *)&password;
2403
+ }
2404
+ #endif
2405
+
2406
+ SIGAR_DECLARE(char *) sigar_password_get(const char *prompt)
2407
+ {
2408
+ char *buf = NULL;
2409
+
2410
+ /* the linux version of getpass prints the prompt to the tty; ok.
2411
+ * the solaris version prints the prompt to stderr; not ok.
2412
+ * so print the prompt to /dev/tty ourselves if possible (always should be)
2413
+ */
2414
+
2415
+ FILE *tty = NULL;
2416
+
2417
+ if ((tty = fopen("/dev/tty", "w"))) {
2418
+ fprintf(tty, "%s", prompt);
2419
+ fflush(tty);
2420
+
2421
+ buf = getpass(tty ? "" : prompt);
2422
+ fclose(tty);
2423
+ }
2424
+
2425
+ return buf;
2426
+ }
2427
+
2428
+ #endif /* WIN32 */