8b1c9045e14a0611e50d1f5e5d49cee67e1af82a
[bcm963xx.git] / userapps / opensource / net-snmp / agent / mibgroup / mibII / system_mib.c
1 /*
2  *  System MIB group implementation - system.c
3  *
4  */
5
6 #include <net-snmp/net-snmp-config.h>
7
8 #if HAVE_STDLIB_H
9 #include <stdlib.h>
10 #endif
11 #ifdef HAVE_UNISTD_H
12 #include <unistd.h>
13 #endif
14 #if HAVE_STRING_H
15 #include <string.h>
16 #else
17 #include <strings.h>
18 #endif
19 #include <sys/types.h>
20 #if HAVE_WINSOCK_H
21 #include <winsock.h>
22 #endif
23
24 #ifdef HAVE_SYS_TIME_H
25 #include <sys/time.h>
26 #endif
27
28 #include <ctype.h>
29 #if HAVE_UTSNAME_H
30 #include <utsname.h>
31 #else
32 #if HAVE_SYS_UTSNAME_H
33 #include <sys/utsname.h>
34 #endif
35 #endif
36 #if HAVE_NETINET_IN_H
37 #include <netinet/in.h>
38 #endif
39
40 #if HAVE_DMALLOC_H
41 #include <dmalloc.h>
42 #endif
43
44 #ifdef BRCM_SNMP_INFO
45 #include "version.h"
46 #endif
47
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>
51
52 #include "util_funcs.h"
53 #include "system_mib.h"
54 #include "struct.h"
55
56 #ifdef SNMP_SYSOR_MIB
57 #include "sysORTable.h"
58 #endif
59
60         /*********************
61          *
62          *  Kernel & interface information,
63          *   and internal forward declarations
64          *
65          *********************/
66
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 };
75
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];
80
81 int             sysServices = 72;
82 int             sysServicesConfiged = 0;
83
84 extern oid      version_id[];
85 extern int      version_id_len;
86
87 static int      sysContactSet = 0, sysLocationSet = 0, sysNameSet = 0;
88
89 WriteMethod     writeSystem;
90 int             header_system(struct variable *, oid *, size_t *, int,
91                               size_t *, WriteMethod **);
92
93         /*********************
94          *
95          *  snmpd.conf config parsing
96          *
97          *********************/
98
99 void
100 system_parse_config_sysdescr(const char *token, char *cptr)
101 {
102     char            tmpbuf[1024];
103
104     if (strlen(cptr) >= sizeof(version_descr)) {
105         snprintf(tmpbuf,
106                  sizeof(tmpbuf),
107                  "sysdescr token too long (must be < %d):\n\t%s",
108                  sizeof(version_descr),
109                  cptr);
110         config_perror(tmpbuf);
111     } else if (strcmp(cptr, "\"\"") == 0) {
112         version_descr[0] = '\0';
113     } else {
114         strcpy(version_descr, cptr);
115     }
116 }
117
118 void
119 system_parse_config_sysloc(const char *token, char *cptr)
120 {
121     char            tmpbuf[1024];
122
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);
128     }
129
130     if (strcmp(token, "psyslocation") == 0) {
131         if (sysLocationSet < 0) {
132             /*
133              * This is bogus (and shouldn't happen anyway) -- the sysLocation
134              * is already configured read-only.  
135              */
136             snmp_log(LOG_WARNING,
137                      "ignoring attempted override of read-only sysLocation.0\n");
138             return;
139         } else {
140             sysLocationSet++;
141         }
142     } else {
143         if (sysLocationSet > 0) {
144             /*
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.  
148              */
149             snmp_log(LOG_WARNING,
150                      "ignoring attempted override of read-only sysLocation.0\n");
151             /*
152              * Fall through and copy in this value.  
153              */
154         }
155         sysLocationSet = -1;
156     }
157
158     if (strcmp(cptr, "\"\"") == 0) {
159         sysLocation[0] = '\0';
160     } else if (strlen(cptr) < sizeof(sysLocation)) {
161         strcpy(sysLocation, cptr);
162     }
163 }
164
165 void
166 system_parse_config_syscon(const char *token, char *cptr)
167 {
168     char            tmpbuf[1024];
169
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);
175     }
176
177     if (strcmp(token, "psyscontact") == 0) {
178         if (sysContactSet < 0) {
179             /*
180              * This is bogus (and shouldn't happen anyway) -- the sysContact
181              * is already configured read-only.  
182              */
183             snmp_log(LOG_WARNING,
184                      "ignoring attempted override of read-only sysContact.0\n");
185             return;
186         } else {
187             sysContactSet++;
188         }
189     } else {
190         if (sysContactSet > 0) {
191             /*
192              * This is bogus (and shouldn't happen anyway) -- we already read a
193              * persistent value of sysContact, which we should ignore in favour
194              * of this one.  
195              */
196             snmp_log(LOG_WARNING,
197                      "ignoring attempted override of read-only sysContact.0\n");
198             /*
199              * Fall through and copy in this value.  
200              */
201         }
202         sysContactSet = -1;
203     }
204
205     if (strcmp(cptr, "\"\"") == 0) {
206         sysContact[0] = '\0';
207     } else if (strlen(cptr) < sizeof(sysContact)) {
208         strcpy(sysContact, cptr);
209     }
210 }
211
212 void
213 system_parse_config_sysname(const char *token, char *cptr)
214 {
215     char            tmpbuf[1024];
216
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);
222     }
223
224     if (strcmp(token, "psysname") == 0) {
225         if (sysNameSet < 0) {
226             /*
227              * This is bogus (and shouldn't happen anyway) -- the sysName
228              * is already configured read-only.  
229              */
230             snmp_log(LOG_WARNING,
231                      "ignoring attempted override of read-only sysName.0\n");
232             return;
233         } else {
234             sysNameSet++;
235         }
236     } else {
237         if (sysNameSet > 0) {
238             /*
239              * This is bogus (and shouldn't happen anyway) -- we already read a
240              * persistent value of sysName, which we should ignore in favour
241              * of this one.  
242              */
243             snmp_log(LOG_WARNING,
244                      "ignoring attempted override of read-only sysName.0\n");
245             /*
246              * Fall through and copy in this value.  
247              */
248         }
249         sysNameSet = -1;
250     }
251
252     if (strcmp(cptr, "\"\"") == 0) {
253         sysName[0] = '\0';
254     } else if (strlen(cptr) < sizeof(sysName)) {
255         strcpy(sysName, cptr);
256     }
257 }
258
259 void
260 system_parse_config_sysServices(const char *token, char *cptr)
261 {
262     sysServices = atoi(cptr);
263     sysServicesConfiged = 1;
264 }
265
266 #ifdef BRCM_SNMP_SUPPORT
267 void system_parse_config_sysObjectID(const char *token, char *cptr)
268 {
269     char tmpbuf[1024];
270
271     sysObjectIDLength = MAX_OID_LEN;
272     if (!read_objid(cptr, sysObjectID, &sysObjectIDLength)) {
273         snprintf(tmpbuf,
274                  sizeof(tmpbuf),
275                  "sysobjectid token not a parsable OID:\n\t%s",
276                  cptr);
277         config_perror(tmpbuf);
278         memcpy(sysObjectID, version_sysoid, sizeof(version_sysoid));
279         sysObjectIDLength = OID_LENGTH(version_sysoid);
280     }
281 }
282 #endif /* BRCM_SNMP_SUPPORT */
283
284         /*********************
285          *
286          *  Initialisation & common implementation functions
287          *
288          *********************/
289
290 /*
291  * define the structure we're going to ask the agent to register our
292  * information at 
293  */
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 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}},
302 #else
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 /* SNMP_SET */
307 #ifdef SNMP_SYSOR_MIB
308     {SYSSERVICES, ASN_INTEGER, RONLY, var_system, 1, {7}},
309     {SYSORLASTCHANGE, ASN_TIMETICKS, RONLY, var_system, 1, {8}}
310 #else
311     {SYSSERVICES, ASN_INTEGER, RONLY, var_system, 1, {7}}
312 #endif
313 };
314 /*
315  * Define the OID pointer to the top of the mib tree that we're
316  * registering underneath
317  */
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;
323
324 static int
325 system_store(int a, int b, void *c, void *d)
326 {
327     int  pid = 0;
328     char line[SNMP_MAXBUF_SMALL];
329     FILE *fs = fopen("/var/run/httpd_pid", "r");
330
331     if (sysLocationSet > 0) {
332         snprintf(line, SNMP_MAXBUF_SMALL, "psyslocation %s", sysLocation);
333         snmpd_store_config(line);
334     }
335     if (sysContactSet > 0) {
336         snprintf(line, SNMP_MAXBUF_SMALL, "psyscontact %s", sysContact);
337         snmpd_store_config(line);
338     }
339     if (sysNameSet > 0) {
340         snprintf(line, SNMP_MAXBUF_SMALL, "psysname %s", sysName);
341         snmpd_store_config(line);
342     }
343
344     // send SIGUSR1 to httpd for storing SNMP set to PSI
345     if ( fs != NULL ) {
346        if ( fgets(line, SNMP_MAXBUF_SMALL - 1, fs) != NULL ) {
347           pid = atoi(line);
348           if ( pid > 0 )
349              kill(pid, SIGUSR1);
350        }
351        fclose(fs);
352     }
353
354     return 0;
355 }
356
357 void
358 init_system_mib(void)
359 {
360 #ifdef BRCM_SNMP_INFO
361   sprintf(version_descr, "U.S. Robotics Software Version %s", SOFTWARE_VERSION);
362 #else
363 #ifdef HAVE_UNAME
364     struct utsname  utsName;
365
366     uname(&utsName);
367     snprintf(version_descr, sizeof(version_descr),
368             "%s %s %s %s %s", utsName.sysname,
369             utsName.nodename, utsName.release, utsName.version,
370             utsName.machine);
371     version_descr[ sizeof(version_descr)-1 ] = 0;
372 #else
373 #if HAVE_EXECV
374     struct extensible extmp;
375
376     /*
377      * set default values of system stuff 
378      */
379     sprintf(extmp.command, "%s -a", UNAMEPROG);
380     /*
381      * setup defaults 
382      */
383     extmp.type = EXECPROC;
384     extmp.next = NULL;
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 */
389 #else
390     strcpy(version_descr, "unknown");
391 #endif
392 #endif
393 #endif /* BRCM_SNMP_INFO */
394
395 #ifdef BRCM_SNMP_INFO
396     strncpy(sysName,"U.S. Robotics",sizeof(sysName));
397 #else
398 #ifdef HAVE_GETHOSTNAME
399     gethostname(sysName, sizeof(sysName));
400 #else
401 #ifdef HAVE_UNAME
402     strncpy(sysName, utsName.nodename, sizeof(sysName));
403 #else
404 #if HAVE_EXECV
405     sprintf(extmp.command, "%s -n", UNAMEPROG);
406     /*
407      * setup defaults 
408      */
409     extmp.type = EXECPROC;
410     extmp.next = NULL;
411     exec_command(&extmp);
412     strncpy(sysName, extmp.output, sizeof(sysName));
413     sysName[strlen(sysName) - 1] = 0;   /* chomp new line */
414 #else
415     strcpy(sysName, "unknown");
416 #endif                          /* HAVE_EXECV */
417 #endif                          /* HAVE_UNAME */
418 #endif                          /* HAVE_GETHOSTNAME */
419
420 #endif /* BRCM_SNMP_INFO */
421
422     /* default sysObjectID */
423     memcpy(sysObjectID, version_sysoid, sizeof(version_sysoid));
424     sysObjectIDLength = OID_LENGTH(version_sysoid);
425
426     /*
427      * register ourselves with the agent to handle our mib tree 
428      */
429     REGISTER_MIB("mibII/system", system_variables, variable1,
430                  system_variables_oid);
431
432 #ifdef SNMP_SYSOR_MIB
433     if (++system_module_count == 3)
434         REGISTER_SYSOR_ENTRY(system_module_oid,
435                              "The MIB module for SNMPv2 entities");
436 #endif
437
438     sysContactSet = sysLocationSet = sysNameSet = 0;
439
440     /*
441      * register our config handlers 
442      */
443     snmpd_register_config_handler("sysdescr",
444                                   system_parse_config_sysdescr, NULL,
445                                   "description");
446     snmpd_register_config_handler("syslocation",
447                                   system_parse_config_sysloc, NULL,
448                                   "location");
449     snmpd_register_config_handler("syscontact", system_parse_config_syscon,
450                                   NULL, "contact-name");
451     snmpd_register_config_handler("sysname", system_parse_config_sysname,
452                                   NULL, "node-name");
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,
458                                   NULL, NULL);
459     snmpd_register_config_handler("sysservices",
460                                   system_parse_config_sysServices, NULL,
461                                   "NUMBER");
462 #ifdef BRCM_SNMP_SUPPORT
463     snmpd_register_config_handler("sysobjectid",
464                                   system_parse_config_sysObjectID, NULL,
465                                   "OID");
466 #endif
467     snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
468                            system_store, NULL);
469
470 }
471
472
473         /*********************
474          *
475          *  System specific implementation functions
476          *
477          *********************/
478
479 #ifdef SNMP_SYSOR_MIB
480 #ifdef USING_MIBII_SYSORTABLE_MODULE
481 extern struct timeval sysOR_lastchange;
482 #endif
483 #endif /* SNMP_SYSOR_MIB */
484
485 u_char         *
486 var_system(struct variable *vp,
487            oid * name,
488            size_t * length,
489            int exact, size_t * var_len, WriteMethod ** write_method)
490 {
491     static u_long   ulret;
492
493     if (header_generic(vp, name, length, exact, var_len, write_method) ==
494         MATCH_FAILED)
495         return NULL;
496
497     switch (vp->magic) {
498     case VERSION_DESCR:
499         *var_len = strlen(version_descr);
500         return (u_char *) version_descr;
501     case VERSIONID:
502         *var_len = sysObjectIDLength * sizeof(sysObjectID[0]);
503         return (u_char *)sysObjectID;
504     case UPTIME:
505         ulret = netsnmp_get_agent_uptime();
506         return ((u_char *) & ulret);
507     case SYSCONTACT:
508         *var_len = strlen(sysContact);
509 #ifdef SNMP_SET
510         *write_method = writeSystem;
511 #else
512         *write_method = NULL;
513 #endif
514         return (u_char *) sysContact;
515     case SYSTEMNAME:
516         *var_len = strlen(sysName);
517 #ifdef SNMP_SET
518         *write_method = writeSystem;
519 #else
520         *write_method = NULL;
521 #endif
522         return (u_char *) sysName;
523     case SYSLOCATION:
524         *var_len = strlen(sysLocation);
525 #ifdef SNMP_SET
526         *write_method = writeSystem;
527 #else
528         *write_method = NULL;
529 #endif
530         return (u_char *) sysLocation;
531     case SYSSERVICES:
532 #if NO_DUMMY_VALUES
533         if (!sysServicesConfiged)
534             return NULL;
535 #endif
536         long_return = sysServices;
537         return (u_char *) & long_return;
538
539 #ifdef SNMP_SYSOR_MIB
540 #ifdef USING_MIBII_SYSORTABLE_MODULE
541     case SYSORLASTCHANGE:
542         ulret = netsnmp_timeval_uptime(&sysOR_lastchange);
543         return ((u_char *) & ulret);
544 #endif
545 #endif /* SNMP_SYSOR_MIB */
546     default:
547         DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_system\n",
548                     vp->magic));
549     }
550     return NULL;
551 }
552
553
554 #ifdef SNMP_SET
555 int
556 writeSystem(int action,
557             u_char * var_val,
558             u_char var_val_type,
559             size_t var_val_len,
560             u_char * statP, oid * name, size_t name_len)
561 {
562     u_char         *cp;
563     char           *buf = NULL, *oldbuf = NULL;
564     int             count, *setvar = NULL;
565
566     switch ((char) name[7]) {
567     case SYSCONTACT:
568         buf = sysContact;
569         oldbuf = oldsysContact;
570         setvar = &sysContactSet;
571         break;
572     case SYSTEMNAME:
573         buf = sysName;
574         oldbuf = oldsysName;
575         setvar = &sysNameSet;
576         break;
577     case SYSLOCATION:
578         buf = sysLocation;
579         oldbuf = oldsysLocation;
580         setvar = &sysLocationSet;
581         break;
582     default:
583         return SNMP_ERR_GENERR; /* ??? */
584     }
585
586     switch (action) {
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;
591         }
592         if (var_val_len > sizeof(sysLocation) - 1) {
593             snmp_log(LOG_ERR, "bad length\n");
594             return SNMP_ERR_WRONGLENGTH;
595         }
596
597         for (cp = var_val, count = 0; count < (int) var_val_len;
598              count++, cp++) {
599             if (!isprint(*cp)) {
600                 snmp_log(LOG_ERR, "not print %x\n", *cp);
601                 return SNMP_ERR_WRONGVALUE;
602             }
603         }
604         if (setvar != NULL && *setvar < 0) {
605             /*
606              * The object is set in a read-only configuration file.  
607              */
608             return SNMP_ERR_NOTWRITABLE;
609         }
610         break;
611
612     case RESERVE2:             /* Allocate memory and similar resources */
613
614         /*
615          * Using static strings, so nothing needs to be done 
616          */
617         break;
618
619     case ACTION:               /* Perform the SET action (if reversible) */
620
621         /*
622          * Save the old value, in case of UNDO 
623          */
624         strcpy(oldbuf, buf);
625         memcpy(buf, var_val, var_val_len);
626         buf[var_val_len] = 0;
627         break;
628
629     case UNDO:                 /* Reverse the SET action and free resources */
630
631         strcpy(buf, oldbuf);
632         oldbuf[0] = 0;
633         break;
634
635     case COMMIT:
636         if (setvar != NULL) {
637             *setvar = 1;
638         }
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));
644
645     case FREE:                 /* Free any resources allocated */
646
647         /*
648          * No resources have been allocated, but "empty" the 'oldbuf' 
649          */
650         oldbuf[0] = 0;
651         break;
652     }
653     return SNMP_ERR_NOERROR;
654 }                               /* end of writeSystem */
655 #endif /* SNMP_SET */
656
657         /*********************
658          *
659          *  Internal implementation functions - None
660          *
661          *********************/