2 * System MIB group implementation - system.c
6 #include <net-snmp/net-snmp-config.h>
19 #include <sys/types.h>
24 #ifdef HAVE_SYS_TIME_H
32 #if HAVE_SYS_UTSNAME_H
33 #include <sys/utsname.h>
37 #include <netinet/in.h>
48 #include <signal.h> // need for SIGUSR1
49 #include <net-snmp/net-snmp-includes.h>
50 #include <net-snmp/agent/net-snmp-agent-includes.h>
52 #include "util_funcs.h"
53 #include "system_mib.h"
56 #ifdef BUILD_SNMP_SYSOR_MIB
57 #include "sysORTable.h"
60 /*********************
62 * Kernel & interface information,
63 * and internal forward declarations
65 *********************/
67 #define SYS_STRING_LEN 256
68 char version_descr[SYS_STRING_LEN] = VERS_DESC;
69 char sysContact[SYS_STRING_LEN] = SYS_CONTACT;
70 char sysName[SYS_STRING_LEN] = SYS_NAME;
71 char sysLocation[SYS_STRING_LEN] = SYS_LOC;
72 oid sysObjectID[MAX_OID_LEN];
73 int sysObjectIDLength;
74 oid version_sysoid[] = { SYSTEM_MIB };
76 char oldversion_descr[SYS_STRING_LEN];
77 char oldsysContact[SYS_STRING_LEN];
78 char oldsysName[SYS_STRING_LEN];
79 char oldsysLocation[SYS_STRING_LEN];
82 int sysServicesConfiged = 0;
84 extern oid version_id[];
85 extern int version_id_len;
87 static int sysContactSet = 0, sysLocationSet = 0, sysNameSet = 0;
89 WriteMethod writeSystem;
90 int header_system(struct variable *, oid *, size_t *, int,
91 size_t *, WriteMethod **);
93 /*********************
95 * snmpd.conf config parsing
97 *********************/
100 system_parse_config_sysdescr(const char *token, char *cptr)
104 if (strlen(cptr) >= sizeof(version_descr)) {
107 "sysdescr token too long (must be < %d):\n\t%s",
108 sizeof(version_descr),
110 config_perror(tmpbuf);
111 } else if (strcmp(cptr, "\"\"") == 0) {
112 version_descr[0] = '\0';
114 strcpy(version_descr, cptr);
119 system_parse_config_sysloc(const char *token, char *cptr)
123 if (strlen(cptr) >= sizeof(sysLocation)) {
124 snprintf(tmpbuf, 1024,
125 "syslocation token too long (must be < %d):\n\t%s",
126 sizeof(sysLocation), cptr);
127 config_perror(tmpbuf);
130 if (strcmp(token, "psyslocation") == 0) {
131 if (sysLocationSet < 0) {
133 * This is bogus (and shouldn't happen anyway) -- the sysLocation
134 * is already configured read-only.
136 snmp_log(LOG_WARNING,
137 "ignoring attempted override of read-only sysLocation.0\n");
143 if (sysLocationSet > 0) {
145 * This is bogus (and shouldn't happen anyway) -- we already read a
146 * persistent value of sysLocation, which we should ignore in
147 * favour of this one.
149 snmp_log(LOG_WARNING,
150 "ignoring attempted override of read-only sysLocation.0\n");
152 * Fall through and copy in this value.
158 if (strcmp(cptr, "\"\"") == 0) {
159 sysLocation[0] = '\0';
160 } else if (strlen(cptr) < sizeof(sysLocation)) {
161 strcpy(sysLocation, cptr);
166 system_parse_config_syscon(const char *token, char *cptr)
170 if (strlen(cptr) >= sizeof(sysContact)) {
171 snprintf(tmpbuf, 1024,
172 "syscontact token too long (must be < %d):\n\t%s",
173 sizeof(sysContact), cptr);
174 config_perror(tmpbuf);
177 if (strcmp(token, "psyscontact") == 0) {
178 if (sysContactSet < 0) {
180 * This is bogus (and shouldn't happen anyway) -- the sysContact
181 * is already configured read-only.
183 snmp_log(LOG_WARNING,
184 "ignoring attempted override of read-only sysContact.0\n");
190 if (sysContactSet > 0) {
192 * This is bogus (and shouldn't happen anyway) -- we already read a
193 * persistent value of sysContact, which we should ignore in favour
196 snmp_log(LOG_WARNING,
197 "ignoring attempted override of read-only sysContact.0\n");
199 * Fall through and copy in this value.
205 if (strcmp(cptr, "\"\"") == 0) {
206 sysContact[0] = '\0';
207 } else if (strlen(cptr) < sizeof(sysContact)) {
208 strcpy(sysContact, cptr);
213 system_parse_config_sysname(const char *token, char *cptr)
217 if (strlen(cptr) >= sizeof(sysName)) {
218 snprintf(tmpbuf, 1024,
219 "sysname token too long (must be < %d):\n\t%s",
220 sizeof(sysName), cptr);
221 config_perror(tmpbuf);
224 if (strcmp(token, "psysname") == 0) {
225 if (sysNameSet < 0) {
227 * This is bogus (and shouldn't happen anyway) -- the sysName
228 * is already configured read-only.
230 snmp_log(LOG_WARNING,
231 "ignoring attempted override of read-only sysName.0\n");
237 if (sysNameSet > 0) {
239 * This is bogus (and shouldn't happen anyway) -- we already read a
240 * persistent value of sysName, which we should ignore in favour
243 snmp_log(LOG_WARNING,
244 "ignoring attempted override of read-only sysName.0\n");
246 * Fall through and copy in this value.
252 if (strcmp(cptr, "\"\"") == 0) {
254 } else if (strlen(cptr) < sizeof(sysName)) {
255 strcpy(sysName, cptr);
260 system_parse_config_sysServices(const char *token, char *cptr)
262 sysServices = atoi(cptr);
263 sysServicesConfiged = 1;
266 #ifdef BRCM_SNMP_SUPPORT
267 void system_parse_config_sysObjectID(const char *token, char *cptr)
271 sysObjectIDLength = MAX_OID_LEN;
272 if (!read_objid(cptr, sysObjectID, &sysObjectIDLength)) {
275 "sysobjectid token not a parsable OID:\n\t%s",
277 config_perror(tmpbuf);
278 memcpy(sysObjectID, version_sysoid, sizeof(version_sysoid));
279 sysObjectIDLength = OID_LENGTH(version_sysoid);
282 #endif /* BRCM_SNMP_SUPPORT */
284 /*********************
286 * Initialisation & common implementation functions
288 *********************/
291 * define the structure we're going to ask the agent to register our
294 struct variable1 system_variables[] = {
295 {VERSION_DESCR, ASN_OCTET_STR, RONLY, var_system, 1, {1}},
296 {VERSIONID, ASN_OBJECT_ID, RONLY, var_system, 1, {2}},
297 {UPTIME, ASN_TIMETICKS, RONLY, var_system, 1, {3}},
298 #ifdef BUILD_SNMP_SET
299 {SYSCONTACT, ASN_OCTET_STR, RWRITE, var_system, 1, {4}},
300 {SYSTEMNAME, ASN_OCTET_STR, RWRITE, var_system, 1, {5}},
301 {SYSLOCATION, ASN_OCTET_STR, RWRITE, var_system, 1, {6}},
303 {SYSCONTACT, ASN_OCTET_STR, RONLY, var_system, 1, {4}},
304 {SYSTEMNAME, ASN_OCTET_STR, RONLY, var_system, 1, {5}},
305 {SYSLOCATION, ASN_OCTET_STR, RONLY, var_system, 1, {6}},
306 #endif /* BUILD_SNMP_SET */
307 #ifdef BUILD_SNMP_SYSOR_MIB
308 {SYSSERVICES, ASN_INTEGER, RONLY, var_system, 1, {7}},
309 {SYSORLASTCHANGE, ASN_TIMETICKS, RONLY, var_system, 1, {8}}
311 {SYSSERVICES, ASN_INTEGER, RONLY, var_system, 1, {7}}
315 * Define the OID pointer to the top of the mib tree that we're
316 * registering underneath
318 oid system_variables_oid[] = { SNMP_OID_MIB2, 1 };
319 oid system_module_oid[] = { SNMP_OID_SNMPMODULES, 1 };
320 int system_module_oid_len =
321 sizeof(system_module_oid) / sizeof(oid);
322 int system_module_count = 0;
325 system_store(int a, int b, void *c, void *d)
328 char line[SNMP_MAXBUF_SMALL];
329 FILE *fs = fopen("/var/run/httpd_pid", "r");
331 if (sysLocationSet > 0) {
332 snprintf(line, SNMP_MAXBUF_SMALL, "psyslocation %s", sysLocation);
333 snmpd_store_config(line);
335 if (sysContactSet > 0) {
336 snprintf(line, SNMP_MAXBUF_SMALL, "psyscontact %s", sysContact);
337 snmpd_store_config(line);
339 if (sysNameSet > 0) {
340 snprintf(line, SNMP_MAXBUF_SMALL, "psysname %s", sysName);
341 snmpd_store_config(line);
344 // send SIGUSR1 to httpd for storing SNMP set to PSI
346 if ( fgets(line, SNMP_MAXBUF_SMALL - 1, fs) != NULL ) {
358 init_system_mib(void)
360 #ifdef BRCM_SNMP_INFO
361 sprintf(version_descr, "U.S. Robotics Software Version %s", SOFTWARE_VERSION);
364 struct utsname utsName;
367 snprintf(version_descr, sizeof(version_descr),
368 "%s %s %s %s %s", utsName.sysname,
369 utsName.nodename, utsName.release, utsName.version,
371 version_descr[ sizeof(version_descr)-1 ] = 0;
374 struct extensible extmp;
377 * set default values of system stuff
379 sprintf(extmp.command, "%s -a", UNAMEPROG);
383 extmp.type = EXECPROC;
385 exec_command(&extmp);
386 strncpy(version_descr, extmp.output, sizeof(version_descr));
387 version_descr[sizeof(version_descr) - 1] = 0;
388 version_descr[strlen(version_descr) - 1] = 0; /* chomp new line */
390 strcpy(version_descr, "unknown");
393 #endif /* BRCM_SNMP_INFO */
395 #ifdef BRCM_SNMP_INFO
396 strncpy(sysName,"U.S. Robotics",sizeof(sysName));
398 #ifdef HAVE_GETHOSTNAME
399 gethostname(sysName, sizeof(sysName));
402 strncpy(sysName, utsName.nodename, sizeof(sysName));
405 sprintf(extmp.command, "%s -n", UNAMEPROG);
409 extmp.type = EXECPROC;
411 exec_command(&extmp);
412 strncpy(sysName, extmp.output, sizeof(sysName));
413 sysName[strlen(sysName) - 1] = 0; /* chomp new line */
415 strcpy(sysName, "unknown");
416 #endif /* HAVE_EXECV */
417 #endif /* HAVE_UNAME */
418 #endif /* HAVE_GETHOSTNAME */
420 #endif /* BRCM_SNMP_INFO */
422 /* default sysObjectID */
423 memcpy(sysObjectID, version_sysoid, sizeof(version_sysoid));
424 sysObjectIDLength = OID_LENGTH(version_sysoid);
427 * register ourselves with the agent to handle our mib tree
429 REGISTER_MIB("mibII/system", system_variables, variable1,
430 system_variables_oid);
432 #ifdef BUILD_SNMP_SYSOR_MIB
433 if (++system_module_count == 3)
434 REGISTER_SYSOR_ENTRY(system_module_oid,
435 "The MIB module for SNMPv2 entities");
438 sysContactSet = sysLocationSet = sysNameSet = 0;
441 * register our config handlers
443 snmpd_register_config_handler("sysdescr",
444 system_parse_config_sysdescr, NULL,
446 snmpd_register_config_handler("syslocation",
447 system_parse_config_sysloc, NULL,
449 snmpd_register_config_handler("syscontact", system_parse_config_syscon,
450 NULL, "contact-name");
451 snmpd_register_config_handler("sysname", system_parse_config_sysname,
453 snmpd_register_config_handler("psyslocation",
454 system_parse_config_sysloc, NULL, NULL);
455 snmpd_register_config_handler("psyscontact",
456 system_parse_config_syscon, NULL, NULL);
457 snmpd_register_config_handler("psysname", system_parse_config_sysname,
459 snmpd_register_config_handler("sysservices",
460 system_parse_config_sysServices, NULL,
462 #ifdef BRCM_SNMP_SUPPORT
463 snmpd_register_config_handler("sysobjectid",
464 system_parse_config_sysObjectID, NULL,
467 snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
473 /*********************
475 * System specific implementation functions
477 *********************/
479 #ifdef BUILD_SNMP_SYSOR_MIB
480 #ifdef USING_MIBII_SYSORTABLE_MODULE
481 extern struct timeval sysOR_lastchange;
483 #endif /* BUILD_SNMP_SYSOR_MIB */
486 var_system(struct variable *vp,
489 int exact, size_t * var_len, WriteMethod ** write_method)
493 if (header_generic(vp, name, length, exact, var_len, write_method) ==
499 *var_len = strlen(version_descr);
500 return (u_char *) version_descr;
502 *var_len = sysObjectIDLength * sizeof(sysObjectID[0]);
503 return (u_char *)sysObjectID;
505 ulret = netsnmp_get_agent_uptime();
506 return ((u_char *) & ulret);
508 *var_len = strlen(sysContact);
509 #ifdef BUILD_SNMP_SET
510 *write_method = writeSystem;
512 *write_method = NULL;
514 return (u_char *) sysContact;
516 *var_len = strlen(sysName);
517 #ifdef BUILD_SNMP_SET
518 *write_method = writeSystem;
520 *write_method = NULL;
522 return (u_char *) sysName;
524 *var_len = strlen(sysLocation);
525 #ifdef BUILD_SNMP_SET
526 *write_method = writeSystem;
528 *write_method = NULL;
530 return (u_char *) sysLocation;
533 if (!sysServicesConfiged)
536 long_return = sysServices;
537 return (u_char *) & long_return;
539 #ifdef BUILD_SNMP_SYSOR_MIB
540 #ifdef USING_MIBII_SYSORTABLE_MODULE
541 case SYSORLASTCHANGE:
542 ulret = netsnmp_timeval_uptime(&sysOR_lastchange);
543 return ((u_char *) & ulret);
545 #endif /* BUILD_SNMP_SYSOR_MIB */
547 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_system\n",
554 #ifdef BUILD_SNMP_SET
556 writeSystem(int action,
560 u_char * statP, oid * name, size_t name_len)
563 char *buf = NULL, *oldbuf = NULL;
564 int count, *setvar = NULL;
566 switch ((char) name[7]) {
569 oldbuf = oldsysContact;
570 setvar = &sysContactSet;
575 setvar = &sysNameSet;
579 oldbuf = oldsysLocation;
580 setvar = &sysLocationSet;
583 return SNMP_ERR_GENERR; /* ??? */
587 case RESERVE1: /* Check values for acceptability */
588 if (var_val_type != ASN_OCTET_STR) {
589 snmp_log(LOG_ERR, "not string\n");
590 return SNMP_ERR_WRONGTYPE;
592 if (var_val_len > sizeof(sysLocation) - 1) {
593 snmp_log(LOG_ERR, "bad length\n");
594 return SNMP_ERR_WRONGLENGTH;
597 for (cp = var_val, count = 0; count < (int) var_val_len;
600 snmp_log(LOG_ERR, "not print %x\n", *cp);
601 return SNMP_ERR_WRONGVALUE;
604 if (setvar != NULL && *setvar < 0) {
606 * The object is set in a read-only configuration file.
608 return SNMP_ERR_NOTWRITABLE;
612 case RESERVE2: /* Allocate memory and similar resources */
615 * Using static strings, so nothing needs to be done
619 case ACTION: /* Perform the SET action (if reversible) */
622 * Save the old value, in case of UNDO
625 memcpy(buf, var_val, var_val_len);
626 buf[var_val_len] = 0;
629 case UNDO: /* Reverse the SET action and free resources */
636 if (setvar != NULL) {
639 snmp_save_persistent(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE));
640 (void) snmp_call_callbacks(SNMP_CALLBACK_LIBRARY,
641 SNMP_CALLBACK_STORE_DATA, NULL);
642 snmp_clean_persistent(netsnmp_ds_get_string
643 (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE));
645 case FREE: /* Free any resources allocated */
648 * No resources have been allocated, but "empty" the 'oldbuf'
653 return SNMP_ERR_NOERROR;
654 } /* end of writeSystem */
655 #endif /* BUILD_SNMP_SET */
657 /*********************
659 * Internal implementation functions - None
661 *********************/