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"
57 #include "sysORTable.h"
60 /*********************
62 * Kernel & interface information,
63 * and internal forward declarations
65 *********************/
66 #define DEFAULT_SYSTEM_MIB 1,3,6,1,4,1,3646,100,7,OSTYPE
68 #define SYS_STRING_LEN 256
69 char version_descr[SYS_STRING_LEN] = VERS_DESC;
70 char sysContact[SYS_STRING_LEN] = SYS_CONTACT;
71 char sysName[SYS_STRING_LEN] = SYS_NAME;
72 char sysLocation[SYS_STRING_LEN] = SYS_LOC;
73 oid sysObjectID[MAX_OID_LEN];
74 int sysObjectIDLength;
75 //oid version_sysoid[] = { SYSTEM_MIB };
76 oid version_sysoid[] = { DEFAULT_SYSTEM_MIB };
78 char oldversion_descr[SYS_STRING_LEN];
79 char oldsysContact[SYS_STRING_LEN];
80 char oldsysName[SYS_STRING_LEN];
81 char oldsysLocation[SYS_STRING_LEN];
84 int sysServicesConfiged = 0;
86 extern oid version_id[];
87 extern int version_id_len;
89 static int sysContactSet = 0, sysLocationSet = 0, sysNameSet = 0;
91 WriteMethod writeSystem;
92 int header_system(struct variable *, oid *, size_t *, int,
93 size_t *, WriteMethod **);
95 /*********************
97 * snmpd.conf config parsing
99 *********************/
102 system_parse_config_sysdescr(const char *token, char *cptr)
106 if (strlen(cptr) >= sizeof(version_descr)) {
109 "sysdescr token too long (must be < %d):\n\t%s",
110 sizeof(version_descr),
112 config_perror(tmpbuf);
113 } else if (strcmp(cptr, "\"\"") == 0) {
114 version_descr[0] = '\0';
116 strcpy(version_descr, cptr);
121 system_parse_config_sysloc(const char *token, char *cptr)
125 if (strlen(cptr) >= sizeof(sysLocation)) {
126 snprintf(tmpbuf, 1024,
127 "syslocation token too long (must be < %d):\n\t%s",
128 sizeof(sysLocation), cptr);
129 config_perror(tmpbuf);
132 if (strcmp(token, "psyslocation") == 0) {
133 if (sysLocationSet < 0) {
135 * This is bogus (and shouldn't happen anyway) -- the sysLocation
136 * is already configured read-only.
138 snmp_log(LOG_WARNING,
139 "ignoring attempted override of read-only sysLocation.0\n");
145 if (sysLocationSet > 0) {
147 * This is bogus (and shouldn't happen anyway) -- we already read a
148 * persistent value of sysLocation, which we should ignore in
149 * favour of this one.
151 snmp_log(LOG_WARNING,
152 "ignoring attempted override of read-only sysLocation.0\n");
154 * Fall through and copy in this value.
160 if (strcmp(cptr, "\"\"") == 0) {
161 sysLocation[0] = '\0';
162 } else if (strlen(cptr) < sizeof(sysLocation)) {
163 strcpy(sysLocation, cptr);
168 system_parse_config_syscon(const char *token, char *cptr)
172 if (strlen(cptr) >= sizeof(sysContact)) {
173 snprintf(tmpbuf, 1024,
174 "syscontact token too long (must be < %d):\n\t%s",
175 sizeof(sysContact), cptr);
176 config_perror(tmpbuf);
179 if (strcmp(token, "psyscontact") == 0) {
180 if (sysContactSet < 0) {
182 * This is bogus (and shouldn't happen anyway) -- the sysContact
183 * is already configured read-only.
185 snmp_log(LOG_WARNING,
186 "ignoring attempted override of read-only sysContact.0\n");
192 if (sysContactSet > 0) {
194 * This is bogus (and shouldn't happen anyway) -- we already read a
195 * persistent value of sysContact, which we should ignore in favour
198 snmp_log(LOG_WARNING,
199 "ignoring attempted override of read-only sysContact.0\n");
201 * Fall through and copy in this value.
207 if (strcmp(cptr, "\"\"") == 0) {
208 sysContact[0] = '\0';
209 } else if (strlen(cptr) < sizeof(sysContact)) {
210 strcpy(sysContact, cptr);
215 system_parse_config_sysname(const char *token, char *cptr)
219 if (strlen(cptr) >= sizeof(sysName)) {
220 snprintf(tmpbuf, 1024,
221 "sysname token too long (must be < %d):\n\t%s",
222 sizeof(sysName), cptr);
223 config_perror(tmpbuf);
226 if (strcmp(token, "psysname") == 0) {
227 if (sysNameSet < 0) {
229 * This is bogus (and shouldn't happen anyway) -- the sysName
230 * is already configured read-only.
232 snmp_log(LOG_WARNING,
233 "ignoring attempted override of read-only sysName.0\n");
239 if (sysNameSet > 0) {
241 * This is bogus (and shouldn't happen anyway) -- we already read a
242 * persistent value of sysName, which we should ignore in favour
245 snmp_log(LOG_WARNING,
246 "ignoring attempted override of read-only sysName.0\n");
248 * Fall through and copy in this value.
254 if (strcmp(cptr, "\"\"") == 0) {
256 } else if (strlen(cptr) < sizeof(sysName)) {
257 strcpy(sysName, cptr);
262 system_parse_config_sysServices(const char *token, char *cptr)
264 sysServices = atoi(cptr);
265 sysServicesConfiged = 1;
268 #ifdef BRCM_SNMP_SUPPORT
269 void system_parse_config_sysObjectID(const char *token, char *cptr)
273 sysObjectIDLength = MAX_OID_LEN;
274 if (!read_objid(cptr, sysObjectID, &sysObjectIDLength)) {
277 "sysobjectid token not a parsable OID:\n\t%s",
279 config_perror(tmpbuf);
280 memcpy(sysObjectID, version_sysoid, sizeof(version_sysoid));
281 sysObjectIDLength = OID_LENGTH(version_sysoid);
284 #endif /* BRCM_SNMP_SUPPORT */
286 /*********************
288 * Initialisation & common implementation functions
290 *********************/
293 * define the structure we're going to ask the agent to register our
296 struct variable1 system_variables[] = {
297 {VERSION_DESCR, ASN_OCTET_STR, RONLY, var_system, 1, {1}},
298 {VERSIONID, ASN_OBJECT_ID, RONLY, var_system, 1, {2}},
299 {UPTIME, ASN_TIMETICKS, RONLY, var_system, 1, {3}},
301 {SYSCONTACT, ASN_OCTET_STR, RWRITE, var_system, 1, {4}},
302 {SYSTEMNAME, ASN_OCTET_STR, RWRITE, var_system, 1, {5}},
303 {SYSLOCATION, ASN_OCTET_STR, RWRITE, var_system, 1, {6}},
305 {SYSCONTACT, ASN_OCTET_STR, RONLY, var_system, 1, {4}},
306 {SYSTEMNAME, ASN_OCTET_STR, RONLY, var_system, 1, {5}},
307 {SYSLOCATION, ASN_OCTET_STR, RONLY, var_system, 1, {6}},
308 #endif /* SNMP_SET */
309 #ifdef SNMP_SYSOR_MIB
310 {SYSSERVICES, ASN_INTEGER, RONLY, var_system, 1, {7}},
311 {SYSORLASTCHANGE, ASN_TIMETICKS, RONLY, var_system, 1, {8}}
313 {SYSSERVICES, ASN_INTEGER, RONLY, var_system, 1, {7}}
317 * Define the OID pointer to the top of the mib tree that we're
318 * registering underneath
320 oid system_variables_oid[] = { SNMP_OID_MIB2, 1 };
321 oid system_module_oid[] = { SNMP_OID_SNMPMODULES, 1 };
322 int system_module_oid_len =
323 sizeof(system_module_oid) / sizeof(oid);
324 int system_module_count = 0;
327 system_store(int a, int b, void *c, void *d)
330 char line[SNMP_MAXBUF_SMALL];
331 FILE *fs = fopen("/var/run/httpd_pid", "r");
333 if (sysLocationSet > 0) {
334 snprintf(line, SNMP_MAXBUF_SMALL, "psyslocation %s", sysLocation);
335 snmpd_store_config(line);
337 if (sysContactSet > 0) {
338 snprintf(line, SNMP_MAXBUF_SMALL, "psyscontact %s", sysContact);
339 snmpd_store_config(line);
341 if (sysNameSet > 0) {
342 snprintf(line, SNMP_MAXBUF_SMALL, "psysname %s", sysName);
343 snmpd_store_config(line);
346 // send SIGUSR1 to httpd for storing SNMP set to PSI
348 if ( fgets(line, SNMP_MAXBUF_SMALL - 1, fs) != NULL ) {
360 init_system_mib(void)
362 #ifdef BRCM_SNMP_INFO
363 //sprintf(version_descr, "Broadcom Bcm963xx Software Version %s", ODM_VERSION);
364 sprintf(version_descr, "BCM96348-based ADSL Router");
367 struct utsname utsName;
370 snprintf(version_descr, sizeof(version_descr),
371 "%s %s %s %s %s", utsName.sysname,
372 utsName.nodename, utsName.release, utsName.version,
374 version_descr[ sizeof(version_descr)-1 ] = 0;
377 struct extensible extmp;
380 * set default values of system stuff
382 sprintf(extmp.command, "%s -a", UNAMEPROG);
386 extmp.type = EXECPROC;
388 exec_command(&extmp);
389 strncpy(version_descr, extmp.output, sizeof(version_descr));
390 version_descr[sizeof(version_descr) - 1] = 0;
391 version_descr[strlen(version_descr) - 1] = 0; /* chomp new line */
393 strcpy(version_descr, "unknown");
396 #endif /* BRCM_SNMP_INFO */
398 #ifdef BRCM_SNMP_INFO
399 strncpy(sysName,"Broadcom",sizeof(sysName));
401 #ifdef HAVE_GETHOSTNAME
402 gethostname(sysName, sizeof(sysName));
405 strncpy(sysName, utsName.nodename, sizeof(sysName));
408 sprintf(extmp.command, "%s -n", UNAMEPROG);
412 extmp.type = EXECPROC;
414 exec_command(&extmp);
415 strncpy(sysName, extmp.output, sizeof(sysName));
416 sysName[strlen(sysName) - 1] = 0; /* chomp new line */
418 strcpy(sysName, "unknown");
419 #endif /* HAVE_EXECV */
420 #endif /* HAVE_UNAME */
421 #endif /* HAVE_GETHOSTNAME */
423 #endif /* BRCM_SNMP_INFO */
425 /* default sysObjectID */
426 memcpy(sysObjectID, version_sysoid, sizeof(version_sysoid));
427 sysObjectIDLength = OID_LENGTH(version_sysoid);
430 * register ourselves with the agent to handle our mib tree
432 REGISTER_MIB("mibII/system", system_variables, variable1,
433 system_variables_oid);
435 #ifdef SNMP_SYSOR_MIB
436 if (++system_module_count == 3)
437 REGISTER_SYSOR_ENTRY(system_module_oid,
438 "The MIB module for SNMPv2 entities");
441 sysContactSet = sysLocationSet = sysNameSet = 0;
444 * register our config handlers
446 snmpd_register_config_handler("sysdescr",
447 system_parse_config_sysdescr, NULL,
449 snmpd_register_config_handler("syslocation",
450 system_parse_config_sysloc, NULL,
452 snmpd_register_config_handler("syscontact", system_parse_config_syscon,
453 NULL, "contact-name");
454 snmpd_register_config_handler("sysname", system_parse_config_sysname,
456 snmpd_register_config_handler("psyslocation",
457 system_parse_config_sysloc, NULL, NULL);
458 snmpd_register_config_handler("psyscontact",
459 system_parse_config_syscon, NULL, NULL);
460 snmpd_register_config_handler("psysname", system_parse_config_sysname,
462 snmpd_register_config_handler("sysservices",
463 system_parse_config_sysServices, NULL,
465 #ifdef BRCM_SNMP_SUPPORT
466 snmpd_register_config_handler("sysobjectid",
467 system_parse_config_sysObjectID, NULL,
470 snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
476 /*********************
478 * System specific implementation functions
480 *********************/
482 #ifdef SNMP_SYSOR_MIB
483 #ifdef USING_MIBII_SYSORTABLE_MODULE
484 extern struct timeval sysOR_lastchange;
486 #endif /* SNMP_SYSOR_MIB */
489 var_system(struct variable *vp,
492 int exact, size_t * var_len, WriteMethod ** write_method)
496 if (header_generic(vp, name, length, exact, var_len, write_method) ==
502 *var_len = strlen(version_descr);
503 return (u_char *) version_descr;
505 *var_len = sysObjectIDLength * sizeof(sysObjectID[0]);
506 return (u_char *)sysObjectID;
508 ulret = netsnmp_get_agent_uptime();
509 return ((u_char *) & ulret);
511 *var_len = strlen(sysContact);
513 *write_method = writeSystem;
515 *write_method = NULL;
517 return (u_char *) sysContact;
519 *var_len = strlen(sysName);
521 *write_method = writeSystem;
523 *write_method = NULL;
525 return (u_char *) sysName;
527 *var_len = strlen(sysLocation);
529 *write_method = writeSystem;
531 *write_method = NULL;
533 return (u_char *) sysLocation;
536 if (!sysServicesConfiged)
539 long_return = sysServices;
540 return (u_char *) & long_return;
542 #ifdef SNMP_SYSOR_MIB
543 #ifdef USING_MIBII_SYSORTABLE_MODULE
544 case SYSORLASTCHANGE:
545 ulret = netsnmp_timeval_uptime(&sysOR_lastchange);
546 return ((u_char *) & ulret);
548 #endif /* SNMP_SYSOR_MIB */
550 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_system\n",
559 writeSystem(int action,
563 u_char * statP, oid * name, size_t name_len)
566 char *buf = NULL, *oldbuf = NULL;
567 int count, *setvar = NULL;
569 switch ((char) name[7]) {
572 oldbuf = oldsysContact;
573 setvar = &sysContactSet;
578 setvar = &sysNameSet;
582 oldbuf = oldsysLocation;
583 setvar = &sysLocationSet;
586 return SNMP_ERR_GENERR; /* ??? */
590 case RESERVE1: /* Check values for acceptability */
591 if (var_val_type != ASN_OCTET_STR) {
592 snmp_log(LOG_ERR, "not string\n");
593 return SNMP_ERR_WRONGTYPE;
595 if (var_val_len > sizeof(sysLocation) - 1) {
596 snmp_log(LOG_ERR, "bad length\n");
597 return SNMP_ERR_WRONGLENGTH;
600 for (cp = var_val, count = 0; count < (int) var_val_len;
603 snmp_log(LOG_ERR, "not print %x\n", *cp);
604 return SNMP_ERR_WRONGVALUE;
607 if (setvar != NULL && *setvar < 0) {
609 * The object is set in a read-only configuration file.
611 return SNMP_ERR_NOTWRITABLE;
615 case RESERVE2: /* Allocate memory and similar resources */
618 * Using static strings, so nothing needs to be done
622 case ACTION: /* Perform the SET action (if reversible) */
625 * Save the old value, in case of UNDO
628 memcpy(buf, var_val, var_val_len);
629 buf[var_val_len] = 0;
632 case UNDO: /* Reverse the SET action and free resources */
639 if (setvar != NULL) {
642 snmp_save_persistent(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE));
643 (void) snmp_call_callbacks(SNMP_CALLBACK_LIBRARY,
644 SNMP_CALLBACK_STORE_DATA, NULL);
645 snmp_clean_persistent(netsnmp_ds_get_string
646 (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE));
648 case FREE: /* Free any resources allocated */
651 * No resources have been allocated, but "empty" the 'oldbuf'
656 return SNMP_ERR_NOERROR;
657 } /* end of writeSystem */
658 #endif /* SNMP_SET */
660 /*********************
662 * Internal implementation functions - None
664 *********************/