Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_scalars.c
108735 views
1
/*-
2
* Copyright (c) 2005-2006 The FreeBSD Project
3
* All rights reserved.
4
*
5
* Author: Victor Cruceru <[email protected]>
6
*
7
* Redistribution of this software and documentation and use in source and
8
* binary forms, with or without modification, are permitted provided that
9
* the following conditions are met:
10
*
11
* 1. Redistributions of source code or documentation must retain the above
12
* copyright notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
/*
31
* Host Resources MIB scalars implementation for SNMPd.
32
*/
33
34
#include <sys/param.h>
35
#include <sys/sysctl.h>
36
37
#include <pwd.h>
38
#include <stdlib.h>
39
#include <stdint.h>
40
#include <string.h>
41
#include <syslog.h>
42
#include <utmpx.h>
43
44
#include "hostres_snmp.h"
45
#include "hostres_oid.h"
46
#include "hostres_tree.h"
47
48
/* physical memory size in Kb */
49
static uint64_t phys_mem_size;
50
51
/* boot line (malloced) */
52
static u_char *boot_line;
53
54
/* maximum number of processes */
55
static uint32_t max_proc;
56
57
/**
58
* Free all static data
59
*/
60
void
61
fini_scalars(void)
62
{
63
64
free(boot_line);
65
}
66
67
/**
68
* Get system uptime in hundredths of seconds since the epoch
69
* Returns 0 in case of an error
70
*/
71
static int
72
OS_getSystemUptime(uint32_t *ut)
73
{
74
uint64_t uptime;
75
struct timespec ts;
76
77
if (clock_gettime(CLOCK_UPTIME, &ts)) {
78
syslog(LOG_ERR, "clock_gettime failed: %m");
79
return (SNMP_ERR_GENERR);
80
}
81
82
uptime = ts.tv_sec * 100 + ts.tv_nsec / 1000000;
83
if (uptime > UINT32_MAX)
84
*ut = UINT32_MAX;
85
else
86
*ut = (uint32_t)uptime;
87
88
return (SNMP_ERR_NOERROR);
89
}
90
91
/**
92
* Get system local date and time in a foramt suitable for DateAndTime TC:
93
* field octets contents range
94
* ----- ------ -------- -----
95
* 1 1-2 year* 0..65536
96
* 2 3 month 1..12
97
* 3 4 day 1..31
98
* 4 5 hour 0..23
99
* 5 6 minutes 0..59
100
* 6 7 seconds 0..60
101
* (use 60 for leap-second)
102
* 7 8 deci-seconds 0..9
103
* 8 9 direction from UTC '+' / '-'
104
* 9 10 hours from UTC* 0..13
105
* 10 11 minutes from UTC 0..59
106
*
107
* * Notes:
108
* - the value of year is in network-byte order
109
* - daylight saving time in New Zealand is +13
110
*
111
* For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be
112
* displayed as:
113
*
114
* 1992-5-26,13:30:15.0,-4:0
115
*
116
* Returns -1 in case of an error or the length of the string (8 or 11)
117
* Actually returns always 11 on freebsd
118
*/
119
static int
120
OS_getSystemDate(struct snmp_value *value)
121
{
122
u_char s_date_time[11];
123
struct tm tloc_tm;
124
time_t tloc_time_t;
125
struct timeval right_now;
126
int string_len;
127
128
if (gettimeofday(&right_now, NULL) < 0) {
129
syslog(LOG_ERR, "gettimeofday failed: %m");
130
return (SNMP_ERR_GENERR);
131
}
132
133
tloc_time_t = right_now.tv_sec;
134
135
if (localtime_r(&tloc_time_t, &tloc_tm) == NULL) {
136
syslog(LOG_ERR, "localtime_r() failed: %m ");
137
return (SNMP_ERR_GENERR);
138
}
139
140
string_len = make_date_time(s_date_time, &tloc_tm,
141
right_now.tv_usec / 100000);
142
143
return (string_get(value, s_date_time, string_len));
144
}
145
146
/**
147
* Get kernel boot path. For FreeBSD it seems that no arguments are
148
* present. Returns NULL if an error occurred. The returned data is a
149
* pointer to a global storage.
150
*/
151
int
152
OS_getSystemInitialLoadParameters(u_char **params)
153
{
154
155
if (boot_line == NULL) {
156
int mib[2] = { CTL_KERN, KERN_BOOTFILE };
157
char *buf;
158
size_t buf_len = 0;
159
160
/* get the needed buffer len */
161
if (sysctl(mib, 2, NULL, &buf_len, NULL, 0) != 0) {
162
syslog(LOG_ERR,
163
"sysctl({CTL_KERN,KERN_BOOTFILE}) failed: %m");
164
return (SNMP_ERR_GENERR);
165
}
166
167
if ((buf = malloc(buf_len)) == NULL) {
168
syslog(LOG_ERR, "malloc failed");
169
return (SNMP_ERR_GENERR);
170
}
171
if (sysctl(mib, 2, buf, &buf_len, NULL, 0)) {
172
syslog(LOG_ERR,
173
"sysctl({CTL_KERN,KERN_BOOTFILE}) failed: %m");
174
free(buf);
175
return (SNMP_ERR_GENERR);
176
}
177
178
boot_line = buf;
179
HRDBG("kernel boot file: %s", boot_line);
180
}
181
182
*params = boot_line;
183
return (SNMP_ERR_NOERROR);
184
}
185
186
/**
187
* Get number of current users which are logged in
188
*/
189
static int
190
OS_getSystemNumUsers(uint32_t *nu)
191
{
192
struct utmpx *utmp;
193
194
setutxent();
195
*nu = 0;
196
while ((utmp = getutxent()) != NULL) {
197
if (utmp->ut_type == USER_PROCESS)
198
(*nu)++;
199
}
200
endutxent();
201
202
return (SNMP_ERR_NOERROR);
203
}
204
205
/**
206
* Get number of current processes existing into the system
207
*/
208
static int
209
OS_getSystemProcesses(uint32_t *proc_count)
210
{
211
int pc;
212
213
if (hr_kd == NULL)
214
return (SNMP_ERR_GENERR);
215
216
if (kvm_getprocs(hr_kd, KERN_PROC_PROC, 0, &pc) == NULL) {
217
syslog(LOG_ERR, "kvm_getprocs failed: %m");
218
return (SNMP_ERR_GENERR);
219
}
220
221
*proc_count = pc;
222
return (SNMP_ERR_NOERROR);
223
}
224
225
/**
226
* Get maximum number of processes allowed on this system
227
*/
228
static int
229
OS_getSystemMaxProcesses(uint32_t *mproc)
230
{
231
232
if (max_proc == 0) {
233
int mib[2] = { CTL_KERN, KERN_MAXPROC };
234
int mp;
235
size_t len = sizeof(mp);
236
237
if (sysctl(mib, 2, &mp, &len, NULL, 0) == -1) {
238
syslog(LOG_ERR, "sysctl KERN_MAXPROC failed: %m");
239
return (SNMP_ERR_GENERR);
240
}
241
max_proc = mp;
242
}
243
244
*mproc = max_proc;
245
return (SNMP_ERR_NOERROR);
246
}
247
248
/*
249
* Get the physical memory size in Kbytes.
250
* Returns SNMP error code.
251
*/
252
static int
253
OS_getMemorySize(uint32_t *ms)
254
{
255
256
if (phys_mem_size == 0) {
257
int mib[2] = { CTL_HW, HW_PHYSMEM };
258
u_long physmem;
259
size_t len = sizeof(physmem);
260
261
if (sysctl(mib, 2, &physmem, &len, NULL, 0) == -1) {
262
syslog(LOG_ERR,
263
"sysctl({ CTL_HW, HW_PHYSMEM }) failed: %m");
264
return (SNMP_ERR_GENERR);
265
}
266
267
phys_mem_size = physmem / 1024;
268
}
269
270
if (phys_mem_size > UINT32_MAX)
271
*ms = UINT32_MAX;
272
else
273
*ms = phys_mem_size;
274
return (SNMP_ERR_NOERROR);
275
}
276
277
/*
278
* Try to use the s_date_time parameter as a DateAndTime TC to fill in
279
* the second parameter.
280
* Returns 0 on succes and -1 for an error.
281
* Bug: time zone info is not used
282
*/
283
static struct timeval *
284
OS_checkSystemDateInput(const u_char *str, u_int len)
285
{
286
struct tm tm_to_set;
287
time_t t;
288
struct timeval *tv;
289
290
if (len != 8 && len != 11)
291
return (NULL);
292
293
if (str[2] == 0 || str[2] > 12 ||
294
str[3] == 0 || str[3] > 31 ||
295
str[4] > 23 || str[5] > 59 || str[6] > 60 || str[7] > 9)
296
return (NULL);
297
298
tm_to_set.tm_year = ((str[0] << 8) + str[1]) - 1900;
299
tm_to_set.tm_mon = str[2] - 1;
300
tm_to_set.tm_mday = str[3];
301
tm_to_set.tm_hour = str[4];
302
tm_to_set.tm_min = str[5];
303
tm_to_set.tm_sec = str[6];
304
tm_to_set.tm_isdst = 0;
305
306
/* now make UTC from it */
307
if ((t = timegm(&tm_to_set)) == (time_t)-1)
308
return (NULL);
309
310
/* now apply timezone if specified */
311
if (len == 11) {
312
if (str[9] > 13 || str[10] > 59)
313
return (NULL);
314
if (str[8] == '+')
315
t += 3600 * str[9] + 60 * str[10];
316
else
317
t -= 3600 * str[9] + 60 * str[10];
318
}
319
320
if ((tv = malloc(sizeof(*tv))) == NULL)
321
return (NULL);
322
323
tv->tv_sec = t;
324
tv->tv_usec = (int32_t)str[7] * 100000;
325
326
return (tv);
327
}
328
329
/*
330
* Set system date and time. Timezone is not changed
331
*/
332
static int
333
OS_setSystemDate(const struct timeval *timeval_to_set)
334
{
335
if (settimeofday(timeval_to_set, NULL) == -1) {
336
syslog(LOG_ERR, "settimeofday failed: %m");
337
return (SNMP_ERR_GENERR);
338
}
339
return (SNMP_ERR_NOERROR);
340
}
341
342
/*
343
* prototype of this function was generated by gensnmptree tool in header file
344
* hostres_tree.h
345
* Returns SNMP_ERR_NOERROR on success
346
*/
347
int
348
op_hrSystem(struct snmp_context *ctx, struct snmp_value *value,
349
u_int sub, u_int iidx __unused, enum snmp_op curr_op)
350
{
351
int err;
352
u_char *str;
353
354
switch (curr_op) {
355
356
case SNMP_OP_GET:
357
switch (value->var.subs[sub - 1]) {
358
359
case LEAF_hrSystemUptime:
360
return (OS_getSystemUptime(&value->v.uint32));
361
362
case LEAF_hrSystemDate:
363
return (OS_getSystemDate(value));
364
365
case LEAF_hrSystemInitialLoadDevice:
366
value->v.uint32 = 0; /* FIXME */
367
return (SNMP_ERR_NOERROR);
368
369
case LEAF_hrSystemInitialLoadParameters:
370
if ((err = OS_getSystemInitialLoadParameters(&str)) !=
371
SNMP_ERR_NOERROR)
372
return (err);
373
return (string_get(value, str, -1));
374
375
case LEAF_hrSystemNumUsers:
376
return (OS_getSystemNumUsers(&value->v.uint32));
377
378
case LEAF_hrSystemProcesses:
379
return (OS_getSystemProcesses(&value->v.uint32));
380
381
case LEAF_hrSystemMaxProcesses:
382
return (OS_getSystemMaxProcesses(&value->v.uint32));
383
}
384
abort();
385
386
case SNMP_OP_SET:
387
switch (value->var.subs[sub - 1]) {
388
389
case LEAF_hrSystemDate:
390
if ((ctx->scratch->ptr1 =
391
OS_checkSystemDateInput(value->v.octetstring.octets,
392
value->v.octetstring.len)) == NULL)
393
return (SNMP_ERR_WRONG_VALUE);
394
395
return (SNMP_ERR_NOERROR);
396
397
case LEAF_hrSystemInitialLoadDevice:
398
case LEAF_hrSystemInitialLoadParameters:
399
return (SNMP_ERR_NOT_WRITEABLE);
400
401
}
402
abort();
403
404
case SNMP_OP_ROLLBACK:
405
switch (value->var.subs[sub - 1]) {
406
407
case LEAF_hrSystemDate:
408
free(ctx->scratch->ptr1);
409
return (SNMP_ERR_NOERROR);
410
411
case LEAF_hrSystemInitialLoadDevice:
412
case LEAF_hrSystemInitialLoadParameters:
413
abort();
414
}
415
abort();
416
417
case SNMP_OP_COMMIT:
418
switch (value->var.subs[sub - 1]) {
419
420
case LEAF_hrSystemDate:
421
(void)OS_setSystemDate(ctx->scratch->ptr1);
422
free(ctx->scratch->ptr1);
423
return (SNMP_ERR_NOERROR);
424
425
case LEAF_hrSystemInitialLoadDevice:
426
case LEAF_hrSystemInitialLoadParameters:
427
abort();
428
}
429
abort();
430
431
case SNMP_OP_GETNEXT:
432
abort();
433
}
434
abort();
435
}
436
437
/*
438
* prototype of this function was generated by gensnmptree tool
439
* in the header file hostres_tree.h
440
* Returns SNMP_ERR_NOERROR on success
441
*/
442
int
443
op_hrStorage(struct snmp_context *ctx __unused, struct snmp_value *value,
444
u_int sub, u_int iidx __unused, enum snmp_op curr_op)
445
{
446
447
/* only GET is possible */
448
switch (curr_op) {
449
450
case SNMP_OP_GET:
451
switch (value->var.subs[sub - 1]) {
452
453
case LEAF_hrMemorySize:
454
return (OS_getMemorySize(&value->v.uint32));
455
}
456
abort();
457
458
case SNMP_OP_SET:
459
return (SNMP_ERR_NOT_WRITEABLE);
460
461
case SNMP_OP_ROLLBACK:
462
case SNMP_OP_COMMIT:
463
case SNMP_OP_GETNEXT:
464
abort();
465
}
466
abort();
467
}
468
469