1 /* GKrellM
2 | Copyright (C) 1999-2019 Bill Wilson
3 |
4 | Author: Bill Wilson billw@gkrellm.net
5 | Latest versions might be found at: http://gkrellm.net
6 |
7 | netbsd.c code is Copyright (C):
8 | Anthony Mallet <anthony.mallet@useless-ficus.net>
9 |
10 |
11 | GKrellM is free software: you can redistribute it and/or modify it
12 | under the terms of the GNU General Public License as published by
13 | the Free Software Foundation, either version 3 of the License, or
14 | (at your option) any later version.
15 |
16 | GKrellM is distributed in the hope that it will be useful, but WITHOUT
new(entry_types: &::wasm_bindgen::JsValue) -> Self17 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 | License for more details.
20 |
21 | You should have received a copy of the GNU General Public License
22 | along with this program. If not, see http://www.gnu.org/licenses/
23 |
24 |
25 | Additional permission under GNU GPL version 3 section 7
26 |
27 | If you modify this program, or any covered work, by linking or
28 | combining it with the OpenSSL project's OpenSSL library (or a
29 | modified version of that library), containing parts covered by
30 | the terms of the OpenSSL or SSLeay licenses, you are granted
31 | additional permission to convey the resulting work.
32 | Corresponding Source for a non-source form of such a combination
33 | shall include the source code for the parts of OpenSSL used as well
34 | as that of the covered work.
35 */
36
37 #include <kvm.h>
38
39 kvm_t *kvmd = NULL;
40 char errbuf[_POSIX2_LINE_MAX];
41
42
entry_types(&mut self, val: &::wasm_bindgen::JsValue) -> &mut Self43 void
44 gkrellm_sys_main_init(void)
45 {
46 /* We just ignore error, here. Even if GKrellM doesn't have
47 | kmem privilege, it runs with available information.
48 */
49 kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
50 if (setgid(getgid()) != 0)
51 {
52 fprintf(stderr, "Can't drop setgid privileges.");
53 exit(1);
54 }
55 }
56
57 void
58 gkrellm_sys_main_cleanup(void)
59 {
60 }
61
62
63 /* ===================================================================== */
64 /* CPU monitor interface */
65
66 #include <sys/param.h>
67 #include <sys/sysctl.h>
68 #include <sys/sched.h>
69
70 static gint ncpus;
71
72 static gint get_ncpus(void);
73
74 void
75 gkrellm_sys_cpu_read_data(void)
76 {
77 static int mib[] = { CTL_KERN, KERN_CP_TIME };
78 u_int64_t cp_time[ncpus][CPUSTATES];
79 int n;
80 size_t len;
81
82 if (ncpus > 1) {
83 len = sizeof(cp_time[0]);
84 /* The sysctl() is magic -- it returns the aggregate if
85 there's not enough room for all CPU's. */
86 if (sysctl(mib, 2, cp_time, &len, NULL, 0) == 0)
87 gkrellm_cpu_assign_composite_data(cp_time[0][CP_USER],
88 cp_time[0][CP_NICE], cp_time[0][CP_SYS], cp_time[0][CP_IDLE]);
89 }
90
91 len = sizeof(cp_time);
92 if (sysctl(mib, 2, cp_time, &len, NULL, 0) < 0) return;
93 for (n = 0; n < ncpus; n++)
94 gkrellm_cpu_assign_data(n, cp_time[n][CP_USER],
95 cp_time[n][CP_NICE], cp_time[n][CP_SYS], cp_time[n][CP_IDLE]);
96 }
97
98 gboolean
99 gkrellm_sys_cpu_init(void)
100 {
101 ncpus = get_ncpus();
102 gkrellm_cpu_set_number_of_cpus(ncpus);
103 return TRUE;
104 }
105
106 static gint
107 get_ncpus(void)
108 {
109 static int mib[] = { CTL_HW, HW_NCPU };
110 int ncpus;
111 size_t len = sizeof(int);
112
113 if (sysctl(mib, 2, &ncpus, &len, NULL, 0) < 0)
114 return 1;
115 else
116 return ncpus;
117 }
118
119
120 /* ===================================================================== */
121 /* Proc monitor interface */
122
123 #include <sys/proc.h>
124 #include <sys/sysctl.h>
125 #include <uvm/uvm_extern.h>
126
127 #include <utmp.h>
128
129 void
130 gkrellm_sys_proc_read_data(void)
131 {
132 int mib[6];
133 double avenrun;
134 guint n_forks = 0, n_processes = 0;
135 struct uvmexp_sysctl uvmexp;
136 size_t size;
137
138 mib[0] = CTL_KERN;
139 mib[1] = KERN_PROC2;
140 mib[2] = KERN_PROC_ALL;
141 mib[3] = 0;
142 mib[4] = sizeof(struct kinfo_proc2);
143 mib[5] = 0;
144 if (sysctl(mib, 6, NULL, &size, NULL, 0) >= 0) {
145 n_processes = size / sizeof(struct kinfo_proc2);
146 }
147
148 mib[0] = CTL_VM;
149 mib[1] = VM_UVMEXP2;
150 size = sizeof(uvmexp);
151 if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) >= 0) {
152 n_forks = uvmexp.forks;
153 }
154
155 if (getloadavg(&avenrun, 1) <= 0)
156 avenrun = 0;
157 gkrellm_proc_assign_data(n_processes, 0, n_forks, avenrun);
158 }
159
160 void
161 gkrellm_sys_proc_read_users(void)
162 {
163 gint n_users;
164 static time_t utmp_mtime;
165 struct utmp utmp;
166 struct stat s;
167 FILE *ut;
168
169 if (stat(_PATH_UTMP, &s) == 0 && s.st_mtime != utmp_mtime)
170 {
171 if ((ut = fopen(_PATH_UTMP, "r")) != NULL)
172 {
173 n_users = 0;
174 while (fread(&utmp, sizeof(utmp), 1, ut))
175 {
176 if (utmp.ut_name[0] == '\0') continue;
177 ++n_users;
178 }
179 (void)fclose(ut);
180 gkrellm_proc_assign_users(n_users);
181 }
182 utmp_mtime = s.st_mtime;
183 }
184 }
185
186 gboolean
187 gkrellm_sys_proc_init(void)
188 {
189 return TRUE;
190 }
191
192
193 /* ===================================================================== */
194 /* Memory/Swap monitor interface */
195
196 #include <sys/vmmeter.h>
197 #include <sys/sysctl.h>
198 #include <uvm/uvm_extern.h>
199
200
201 void
202 gkrellm_sys_mem_read_data(void)
203 {
204 int mib[2];
205 guint64 total, used, free, shared, buffers, cached;
206 struct vmtotal vmt;
207 struct uvmexp_sysctl uvmexp;
208 size_t len;
209
210 mib[0] = CTL_VM;
211 mib[1] = VM_METER;
212 len = sizeof(vmt);
213 if (sysctl(mib, 2, &vmt, &len, NULL, 0) < 0)
214 memset(&vmt, 0, sizeof(vmt));
215
216 mib[0] = CTL_VM;
217 mib[1] = VM_UVMEXP2;
218 len = sizeof(uvmexp);
219 if (sysctl(mib, 2, &uvmexp, &len, NULL, 0) < 0)
220 memset(&uvmexp, 0, sizeof(uvmexp));
221
222 total = uvmexp.npages << uvmexp.pageshift;
223
224 /* not sure of what must be computed */
225 free = (uvmexp.inactive + uvmexp.free) << uvmexp.pageshift;
226 shared = vmt.t_rmshr << uvmexp.pageshift;
227
228 /* can't use "uvmexp.active << uvmexp.pageshift" here because the
229 * display for "free" uses "total - used" which is very wrong. */
230 used = total - free;
231
232 /* don't know how to get those values */
233 buffers = 0;
234 cached = 0;
235
236 gkrellm_mem_assign_data(total, used, free, shared, buffers, cached);
237
238 }
239
240 void
241 gkrellm_sys_swap_read_data(void)
242 {
243 static int pgout, pgin;
244 int mib[2];
245 struct uvmexp_sysctl uvmexp;
246 size_t len;
247 static gulong swapin = 0, swapout = 0;
248 guint64 swap_total, swap_used;
249
250 mib[0] = CTL_VM;
251 mib[1] = VM_UVMEXP2;
252 len = sizeof(uvmexp);
253 if (sysctl(mib, 2, &uvmexp, &len, NULL, 0) < 0)
254 memset(&uvmexp, 0, sizeof(uvmexp));
255
256 /* show only the pages located on the disk and not in memory */
257 swap_total = (guint64) (uvmexp.swpages << uvmexp.pageshift);
258 swap_used = (guint64) (uvmexp.swpgonly << uvmexp.pageshift);
259
260 /* For page in/out operations, uvmexp struct doesn't seem to be reliable */
261
262 /* if the number of swapped pages that are in memory (inuse - only) is
263 * greater that the previous value (pgin), we count this a "page in" */
264 if (uvmexp.swpginuse - uvmexp.swpgonly > pgin)
265 swapin += uvmexp.swpginuse - uvmexp.swpgonly - pgin;
266 pgin = uvmexp.swpginuse - uvmexp.swpgonly;
267
268 /* same for page out */
269 if (uvmexp.swpgonly > pgout)
270 swapout += uvmexp.swpgonly - pgout;
271 pgout = uvmexp.swpgonly;
272
273 gkrellm_swap_assign_data(swap_total, swap_used, swapin, swapout);
274 }
275
276 gboolean
277 gkrellm_sys_mem_init(void)
278 {
279 return TRUE;
280 }
281
282
283 /* ===================================================================== */
284 /* Sensor monitor interface */
285
286 /* Tables of voltage correction factors and offsets derived from the
287 | compute lines in sensors.conf. See the README file.
288 */
289 /* "lm78-*" "lm78-j-*" "lm79-*" "w83781d-*" "sis5595-*" "as99127f-*" */
290 /* Values from LM78/LM79 data sheets */
291 #if 0
292 static VoltDefault voltdefault0[] =
293 {
294 { "Vcor1", 1.0, 0, NULL },
295 { "Vcor2", 1.0, 0, NULL },
296 { "+3.3V", 1.0, 0, NULL },
297 { "+5V", 1.68, 0, NULL }, /* in3 ((6.8/10)+1)*@ */
298 { "+12V", 4.0, 0, NULL }, /* in4 ((30/10)+1)*@ */
299 { "-12V", -4.0, 0, NULL }, /* in5 -(240/60)*@ */
300 { "-5V", -1.667, 0, NULL } /* in6 -(100/60)*@ */
301 };
302 #endif
303
304 /* The SENSORS_DIR is not defined as a directory, but directly points on
305 * the "sysmon" device, which implements envsys(4) API. This #define is
306 * not really useful for NetBSD since every sensor will use that device,
307 * but it still provides the location of the device inside the GUI. */
308 #define SENSORS_DIR "/dev/sysmon"
309
310 #include <sys/envsys.h>
311
312
313 /*
314 * get_netbsd_sensor ----------------------------------------------------
315 *
316 * Perform sensor reading
317 */
318 #include <sys/ioctl.h>
319
320 gboolean
321 gkrellm_sys_sensors_get_temperature(gchar *path, gint id,
322 gint iodev, gint interface, gfloat *temp)
323 {
324 envsys_tre_data_t data; /* sensor data */
325
326 data.sensor = interface;
327 if (ioctl(iodev, ENVSYS_GTREDATA, &data) < 0) return FALSE;
328 if (!(data.validflags & (ENVSYS_FVALID|ENVSYS_FCURVALID))) return FALSE;
329
330 if (data.units == ENVSYS_STEMP) {
331 if (temp) /* values in uK */
332 *temp = (data.cur.data_us / 1.0e6) - 273.15/*0K*/ ;
333 return TRUE;
334 }
335
336 return FALSE;
337 }
338
339 gboolean
340 gkrellm_sys_sensors_get_fan(gchar *path, gint id,
341 gint iodev, gint interface, gfloat *fan)
342 {
343 envsys_tre_data_t data; /* sensor data */
344
345 data.sensor = interface;
346 if (ioctl(iodev, ENVSYS_GTREDATA, &data) < 0) return FALSE;
347 if (!(data.validflags & (ENVSYS_FVALID|ENVSYS_FCURVALID))) return FALSE;
348
349 if (data.units == ENVSYS_SFANRPM) {
350 if (fan) /* values in RPM */
351 *fan = data.cur.data_us;
352 return TRUE;
353 }
354 return FALSE;
355 }
356
357 gboolean
358 gkrellm_sys_sensors_get_voltage(gchar *path, gint id,
359 gint iodev, gint interface, gfloat *volt)
360 {
361 envsys_tre_data_t data; /* sensor data */
362
363 data.sensor = interface;
364 if (ioctl(iodev, ENVSYS_GTREDATA, &data) < 0) return FALSE;
365 if (!(data.validflags & (ENVSYS_FVALID|ENVSYS_FCURVALID))) return FALSE;
366
367 if (data.units == ENVSYS_SVOLTS_DC) {
368 if (volt) /* values in uV */
369 *volt = data.cur.data_s / 1.0e6;
370 return TRUE;
371 }
372
373 return FALSE;
374 }
375
376 /*
377 *
378 * At the moment, only two chips are supported: lm78 and alike (see
379 * lm(4)), and VT82C68A South Bridge for VIA chipsets (see viaenv(4)).
380 * Both support the envsys(4) API.
381 *
382 * XXX /dev/sysmon is opened but never closed. This is a problem since
383 * the driver wants an exclusive lock (e.g. envstat won't work when
384 * GKrellM will be running). But, at this time, I don't want to
385 * open/close sysmon each time a reading is needed. See README for
386 * details.
387 */
388
389 gboolean
390 gkrellm_sys_sensors_init(void)
391 {
392 envsys_basic_info_t info; /* sensor misc. info */
393 int fd; /* file desc. for /dev/sysmon */
394 int id = 0; /* incremented for each sensor */
395 int type;
396 char *s, base_name[33];
397 gboolean found_sensors = FALSE;
398
399 /* check if some sensor is configured */
400 fd = open(SENSORS_DIR, O_RDONLY); /* never closed */
401 if (fd < 0) return FALSE;
402
403 /* iterate through available sensors, until the first invalid */
404 for(info.sensor=0; ; info.sensor++) {
405
406 /* stop if we can't ioctl() */
407 if (ioctl(fd, ENVSYS_GTREINFO, &info) < 0) break;
408 /* stop if that sensor is not valid */
409 if (!(info.validflags & ENVSYS_FVALID)) break;
410
411 switch(info.units) {
412 case ENVSYS_STEMP:
413 type = SENSOR_TEMPERATURE; break;
414 case ENVSYS_SFANRPM:
415 type = SENSOR_FAN; break;
416 case ENVSYS_SVOLTS_DC:
417 type = SENSOR_VOLTAGE; break;
418 default:
419 /* unwanted sensor type: continue */
420 continue;
421 }
422
423 /* ok, we've got one working sensor */
424 sprintf(base_name, "%32s", info.desc);
425 /* must map spaces into something else (for config file items) */
426 for(s=strchr(base_name, ' '); s != NULL; s=strchr(s, ' '))
427 *s++ = '_';
428
429 gkrellm_sensors_add_sensor(type, SENSORS_DIR, base_name,
430 id, fd, info.sensor, 1.0,
431 0.0, NULL, NULL);
432 found_sensors = TRUE;
433 }
434 return found_sensors;
435 }
436
437
438
439 /* ===================================================================== */
440 /* Battery monitor interface */
441
442 #if defined(__i386__) || defined(__powerpc__)
443 # include <sys/ioctl.h>
444 # include <machine/apmvar.h>
445
446 # define APMDEV "/dev/apm"
447 #endif
448
449 static int battery_use_apm = 1;
450
451 /* battery data, index by [battery number] */
452 static struct battery_acpi_data {
453 gboolean available; int available_index;
454 gboolean on_line; int on_line_index;
455 gboolean charging; int charging_index;
456 gint full_cap; int full_cap_index;
457 gint cap; int cap_index;
458 gint discharge_rate; int discharge_rate_index;
459 gint charge_rate; int charge_rate_index;
460 } *battery_acpi_data;
461 static int battery_acpi_data_items;
462
463 static int
464 gkrellm_battery_data_alloc(int bat)
465 {
466 if (bat + 1 > battery_acpi_data_items)
467 battery_acpi_data_items = bat + 1;
468
469 battery_acpi_data = realloc(battery_acpi_data,
470 battery_acpi_data_items*
471 sizeof(*battery_acpi_data));
472 return battery_acpi_data?1:0;
473 }
474
475 void
476 gkrellm_sys_battery_read_data(void)
477 {
478 int i;
479 int fd; /* file desc. for /dev/sysmon or /dev/apm */
480 envsys_tre_data_t data; /* sensor data */
481 int time_left;
482
483 if (battery_use_apm) {
484 #if defined(__i386__) || defined(__powerpc__)
485 int r;
486 struct apm_power_info apminfo;
487 gboolean available, on_line, charging;
488 gint percent, time_left;
489
490 if ((fd = open(APMDEV, O_RDONLY)) == -1) return;
491 memset(&apminfo, 0, sizeof(apminfo));
492 r = ioctl(fd, APM_IOC_GETPOWER, &apminfo);
493 close(fd);
494 if (r == -1) return;
495
496 available = (apminfo.battery_state != APM_BATT_UNKNOWN);
497 on_line = (apminfo.ac_state == APM_AC_ON) ? TRUE : FALSE;
498 charging = (apminfo.battery_state == APM_BATT_CHARGING) ? TRUE : FALSE;
499 percent = apminfo.battery_life;
500 time_left = apminfo.minutes_left;
501 gkrellm_battery_assign_data(0, available, on_line, charging,
502 percent, time_left);
503 #else
504 return;
505 #endif
506 }
507
508 fd = open(SENSORS_DIR, O_RDONLY);
509 if (fd < 0) return;
510
511 data.sensor = battery_acpi_data[0].on_line_index;
512 if (ioctl(fd, ENVSYS_GTREDATA, &data) < 0) return;
513 if (!(data.validflags & ENVSYS_FVALID)) return;
514 battery_acpi_data[0].on_line = data.cur.data_us ? TRUE:FALSE;
515
516 /* iterate through available batteries */
517 for(i=0; i<battery_acpi_data_items; i++) {
518 #define read_sensor(x) \
519 do { \
520 data.sensor = battery_acpi_data[i].x ## _index; \
521 if (ioctl(fd, ENVSYS_GTREDATA, &data) < 0) continue; \
522 if (!(data.validflags & ENVSYS_FCURVALID)) \
523 battery_acpi_data[i].x = -1; \
524 else \
525 battery_acpi_data[i].x = data.cur.data_s; \
526 } while(0)
527
528 read_sensor(available);
529 read_sensor(charging);
530 read_sensor(full_cap);
531 read_sensor(cap);
532 read_sensor(discharge_rate);
533 read_sensor(charge_rate);
534 #undef read_sensor
535
536 if (battery_acpi_data[i].discharge_rate > 0)
537 time_left =
538 battery_acpi_data[i].cap * 60 / battery_acpi_data[i].discharge_rate;
539 else if (battery_acpi_data[i].charge_rate > 0)
540 time_left =
541 (battery_acpi_data[i].full_cap - battery_acpi_data[i].cap) * 60 /
542 battery_acpi_data[i].charge_rate;
543 else
544 time_left = -1;
545
546 if (battery_acpi_data[i].available) {
547 gkrellm_battery_assign_data(i,
548 battery_acpi_data[i].available,
549 battery_acpi_data[0].on_line,
550 battery_acpi_data[i].charging,
551
552 /* percent */
553 battery_acpi_data[i].cap * 100 /
554 battery_acpi_data[i].full_cap,
555
556 /* time left (minutes) */
557 time_left);
558 } else
559 gkrellm_battery_assign_data(i, 0, 0, 0, -1, -1);
560 }
561
562 close(fd);
563 }
564
565 gboolean
566 gkrellm_sys_battery_init()
567 {
568 int fd; /* file desc. for /dev/sysmon or /dev/apm */
569 envsys_basic_info_t info; /* sensor misc. info */
570 gboolean found_sensors = FALSE;
571 char fake[2];
572 int r, bat;
573
574 /* --- check APM first --- */
575
576 #if defined(__i386__) || defined(__powerpc__)
577 do {
578 struct apm_power_info info;
579
580 if ((fd = open(APMDEV, O_RDONLY)) == -1) break;
581 r = ioctl(fd, APM_IOC_GETPOWER, &info);
582 close(fd);
583 if (r != -1) {
584 battery_use_apm = 1;
585 return TRUE;
586 }
587 } while(0);
588 #endif
589
590 /* --- check for some envsys(4) acpi battery --- */
591
592 battery_use_apm = 0;
593 battery_acpi_data_items = 0;
594 battery_acpi_data = NULL; /* this is never freed */
595
596 fd = open(SENSORS_DIR, O_RDONLY);
597 if (fd < 0) return FALSE;
598
599 /* iterate through available sensors */
600 for(info.sensor=0; ; info.sensor++) {
601 /* stop if we can't ioctl() */
602 if (ioctl(fd, ENVSYS_GTREINFO, &info) < 0) break;
603 /* stop if that sensor is not valid */
604 if (!(info.validflags & ENVSYS_FVALID)) break;
605
606 do {
607 if (info.units == ENVSYS_INDICATOR &&
608 sscanf(info.desc, "acpibat%d presen%1[t]", &bat, fake) == 2) {
609 if (!gkrellm_battery_data_alloc(bat)) {
610 close(fd);
611 return FALSE;
612 }
613 battery_acpi_data[bat].available_index = info.sensor;
614 found_sensors = TRUE;
615
616 } else if (info.units == ENVSYS_INDICATOR &&
617 sscanf(info.desc, "acpiacad%*d connecte%1[d]", fake) == 1) {
618 if (!gkrellm_battery_data_alloc(0)) {
619 close(fd);
620 return FALSE;
621 }
622 battery_acpi_data[0].on_line_index = info.sensor;
623
624 } else if (info.units == ENVSYS_INDICATOR &&
625 sscanf(info.desc,
626 "acpibat%d chargin%1[g]", &bat, fake) == 2) {
627 if (!gkrellm_battery_data_alloc(bat)) {
628 close(fd);
629 return FALSE;
630 }
631 battery_acpi_data[bat].charging_index = info.sensor;
632 found_sensors = TRUE;
633
634 } else if (info.units == ENVSYS_SAMPHOUR &&
635 sscanf(info.desc,
636 "acpibat%d design ca%1[p]", &bat, fake) == 2) {
637 if (!gkrellm_battery_data_alloc(bat)) {
638 close(fd);
639 return FALSE;
640 }
641 battery_acpi_data[bat].full_cap_index = info.sensor;
642 found_sensors = TRUE;
643
644 } else if (info.units == ENVSYS_SAMPHOUR &&
645 sscanf(info.desc,
646 "acpibat%d charg%1[e]", &bat, fake) == 2) {
647 if (!gkrellm_battery_data_alloc(bat)) {
648 close(fd);
649 return FALSE;
650 }
651 battery_acpi_data[bat].cap_index = info.sensor;
652 found_sensors = TRUE;
653
654 } else if (info.units == ENVSYS_SAMPS &&
655 sscanf(info.desc,
656 "acpibat%d discharge rat%1[e]", &bat, fake) == 2) {
657 if (!gkrellm_battery_data_alloc(bat)) {
658 close(fd);
659 return FALSE;
660 }
661 battery_acpi_data[bat].discharge_rate_index = info.sensor;
662 found_sensors = TRUE;
663
664 } else if (info.units == ENVSYS_SAMPS &&
665 sscanf(info.desc,
666 "acpibat%d charge rat%1[e]", &bat, fake) == 2) {
667 if (!gkrellm_battery_data_alloc(bat)) {
668 close(fd);
669 return FALSE;
670 }
671 battery_acpi_data[bat].charge_rate_index = info.sensor;
672 found_sensors = TRUE;
673 }
674 } while(0);
675 }
676
677 close(fd);
678
679 return found_sensors;
680 }
681
682
683 /* ===================================================================== */
684 /* Disk monitor interface */
685
686 #include <sys/dkstat.h>
687 #include <sys/disk.h>
688 #include <sys/sysctl.h>
689
690 #ifdef HW_IOSTATS
691 #define HW_DISKSTATS HW_IOSTATS
692 #define disk_sysctl io_sysctl
693 #define dk_rbytes rbytes
694 #define dk_wbytes wbytes
695 #define dk_name name
696 #endif
697
698 gboolean
699 gkrellm_sys_disk_init(void)
700 {
701 int mib[3] = { CTL_HW, HW_DISKSTATS, sizeof(struct disk_sysctl) };
702 size_t size;
703
704 /* Just test if the sysctl call works */
705 if (sysctl(mib, 3, NULL, &size, NULL, 0) == -1)
706 return (FALSE);
707
708 return (TRUE);
709 }
710
711 void
712 gkrellm_sys_disk_read_data(void)
713 {
714 int i, n_disks, mib[3] = { CTL_HW, HW_DISKSTATS, sizeof(struct disk_sysctl) };
715 size_t size;
716 guint64 rbytes, wbytes;
717 struct disk_sysctl *dk_drives;
718
719 if (sysctl(mib, 3, NULL, &size, NULL, 0) == -1)
720 return;
721 dk_drives = malloc(size);
722 if (dk_drives == NULL)
723 return;
724 n_disks = size / sizeof(struct disk_sysctl);
725
726 if (sysctl(mib, 3, dk_drives, &size, NULL, 0) == -1)
727 return;
728
729 for (i = 0; i < n_disks; i++) {
730 #if __NetBSD_Version__ >= 106110000
731 rbytes = dk_drives[i].dk_rbytes;
732 wbytes = dk_drives[i].dk_wbytes;
733 #else
734 rbytes = dk_drives[i].dk_bytes;
735 wbytes = 0;
736 #endif
737
738 gkrellm_disk_assign_data_by_name(dk_drives[i].dk_name, rbytes, wbytes, FALSE);
739 }
740
741 free(dk_drives);
742 }
743
744 gchar *
745 gkrellm_sys_disk_name_from_device(gint device_number, gint unit_number,
746 gint *order)
747 {
748 return NULL; /* disk data by device not implemented */
749 }
750
751 gint
752 gkrellm_sys_disk_order_from_name(const gchar *name)
753 {
754 return -1; /* append disk charts as added */
755 }
756
757 #if __NetBSD_Version__ >= 399000100
758
759 #include "../inet.h"
760
761 #include <errno.h>
762 #include <sys/socket.h>
763 #include <netinet/in.h>
764 #include <netinet/tcp_fsm.h>
765
766 static const struct gkrellm_inet_fam {
767 sa_family_t family;
768 const char *mib;
769 } families[] = { {AF_INET, "net.inet.tcp.pcblist"},
770 #ifdef INET6
771 {AF_INET6, "net.inet6.tcp6.pcblist"},
772 #endif
773 {0, NULL} };
774
775 void
776 gkrellm_sys_inet_read_tcp_data()
777 {
778 ActiveTCP tcp;
779 int mib[CTL_MAXNAME], i;
780 size_t sz;
781 u_int namelen;
782 struct kinfo_pcb *pcbt = NULL;
783 const struct gkrellm_inet_fam *pf = families;
784
785 while (pf->mib != NULL) {
786 sz = CTL_MAXNAME;
787 if (sysctlnametomib(pf->mib, mib, &sz) == -1)
788 return;
789 namelen = sz;
790
791 mib[namelen++] = PCB_ALL;
792 mib[namelen++] = 0;
793 mib[namelen++] = sizeof(struct kinfo_pcb);
794 mib[namelen++] = INT_MAX;
795
796 sz = 0;
797 pcbt = NULL;
798 if (sysctl(&mib[0], namelen, pcbt, &sz, NULL, 0) == -1)
799 return;
800 pcbt = malloc(sz);
801 if (pcbt == NULL)
802 return;
803 if (sysctl(&mib[0], namelen, pcbt, &sz, NULL, 0) == -1)
804 return;
805
806 sz /= sizeof(struct kinfo_pcb);
807 for (i = 0; i < sz; i++) {
808 tcp.family = pf->family;
809 if (pf->family == AF_INET) {
810 struct sockaddr_in *sin =
811 (struct sockaddr_in *)&pcbt[i].ki_dst;
812 tcp.remote_addr.s_addr = sin->sin_addr.s_addr;
813 tcp.remote_port = sin->sin_port;
814
815 sin = (struct sockaddr_in *)&pcbt[i].ki_src;
816 tcp.local_port = sin->sin_port;
817 #ifdef INET6
818 } else { /* AF_INET6 */
819 struct sockaddr_in6 *sin =
820 (struct sockaddr_in6 *)&pcbt[i].ki_dst;
821 memcpy(&tcp.remote_addr6, &sin->sin6_addr,
822 sizeof(struct in6_addr));
823 tcp.remote_port = sin->sin6_port;
824
825 sin = (struct sockaddr_in6 *)&pcbt[i].ki_src;
826 tcp.local_port = sin->sin6_port;
827 #endif
828 }
829 if (pcbt[i].ki_tstate == TCPS_ESTABLISHED)
830 gkrellm_inet_log_tcp_port_data(&tcp);
831 }
832 free(pcbt);
833 pf++;
834 }
835 }
836 #endif
837