Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / ntp / dist / ntpsnmpd / ntpSnmpSubagentObject.c
blob9596b6bd2be6e8c01339a845fd8b6ab5307ec103
1 /* $NetBSD$ */
3 /*****************************************************************************
5 * ntpSnmpSubAgentObject.c
7 * This file provides the callback functions for net-snmp and registers the
8 * serviced MIB objects with the master agent.
9 *
10 * Each object has its own callback function that is called by the
11 * master agent process whenever someone queries the corresponding MIB
12 * object.
14 * At the moment this triggers a full send/receive procedure for each
15 * queried MIB object, one of the things that are still on my todo list:
16 * a caching mechanism that reduces the number of requests sent to the
17 * ntpd process.
19 ****************************************************************************/
20 #include <net-snmp/net-snmp-config.h>
21 #include <net-snmp/net-snmp-includes.h>
22 #include <net-snmp/agent/net-snmp-agent-includes.h>
23 #include "ntpSnmpSubagentObject.h"
24 #include <libntpq.h>
26 /* general purpose buffer length definition */
27 #define NTPQ_BUFLEN 2048
29 static int ntpSnmpSubagentObject = 3;
31 char ntpvalue[NTPQ_BUFLEN];
35 /*****************************************************************************
37 * ntpsnmpd_strip_string
39 * This function removes white space characters and EOL chars
40 * from the beginning and end of a given NULL terminated string.
41 * Be aware that the parameter itself is altered.
43 ****************************************************************************
44 * Parameters:
45 * string char* The name of the string variable
46 * NOTE: must be NULL terminated!
47 * Returns:
48 * int length of resulting string (i.e. w/o white spaces)
49 ****************************************************************************/
51 int ntpsnmpd_strip_string(char *string)
53 char newstring[2048] = { 0 };
54 int i = 0;
55 int j = 0;
57 if ( strlen(string) > 2047 )
58 string[2048]=0;
60 j = strlen(string);
62 for (i=0;i<strlen(string);i++)
64 switch(string[i])
66 case 0x09: // Tab
67 case 0x0A: // LF
68 case 0x0D: // CR
69 case ' ': // Space
70 break;
71 default:
72 strncpy(newstring,(char *) &string[i], sizeof(newstring));
73 i=2048;
74 break;
77 strncpy(string, newstring, j);
79 return(strlen(string));
83 /*****************************************************************************
85 * ntpsnmpd_parse_string
87 * This function will parse a given NULL terminated string and cut it
88 * into a fieldname and a value part (using the '=' as the delimiter.
89 * The fieldname will be converted to uppercase and all whitespace
90 * characters are removed from it.
91 * The value part is stripped, e.g. all whitespace characters are removed
92 * from the beginning and end of the string.
93 * If the value is started and ended with quotes ("), they will be removed
94 * and everything between the quotes is left untouched (including
95 * whitespace)
96 * Example:
97 * server host name = hello world!
98 * will result in a field string "SERVERHOSTNAME" and a value
99 * of "hello world!".
100 * My first Parameter = " is this! "
101 * results in a field string "MYFIRSTPARAMETER" and a vaue " is this! "
102 ****************************************************************************
103 * Parameters:
104 * src char* The name of the source string variable
105 * NOTE: must be NULL terminated!
106 * field char* The name of the string which takes the
107 * fieldname
108 * fieldsize int The maximum size of the field name
109 * value char* The name of the string which takes the
110 * value part
111 * valuesize int The maximum size of the value string
113 * Returns:
114 * int length of value string
115 ****************************************************************************/
117 int ntpsnmpd_parse_string(char *src, char *field, int fieldsize, char *value, int valuesize)
119 char string[2048];
120 int i = 0;
121 int j = 0;
122 int l = 0;
123 int a = 0;
125 strncpy(string, src, sizeof(string));
127 a = strlen(string);
129 /* Parsing the field name */
130 for (i=0;l==0;i++)
132 if (i>=a)
133 l=1;
134 else
136 switch(string[i])
138 case 0x09: // Tab
139 case 0x0A: // LF
140 case 0x0D: // CR
141 case ' ': // Space
142 break;
143 case '=':
144 l=1;
145 break;
147 default:
148 if ( j < fieldsize )
150 if ( ( string[i] >= 'a' ) && ( string[i] <='z' ) )
151 field[j++]=( string[i] - 32 ); // convert to Uppercase
152 else
153 field[j++]=string[i];
160 field[j]=0; j=0; value[0]=0;
163 /* Now parsing the value */
164 for (l=0;i<a;i++)
166 if ( ( string[i] > 0x0D ) && ( string[i] != ' ' ) )
167 l = j+1;
169 if ( ( value[0] != 0 ) || ( ( string[i] > 0x0D ) && ( string[i] != ' ' ) ) )
171 if (j < valuesize )
172 value[j++]=string[i];
176 value[l]=0;
178 if ( value[0]=='"' )
179 strcpy(value, (char *) &value[1]);
181 if ( value[strlen(value)-1] == '"' )
182 value[strlen(value)-1]=0;
184 return (strlen(value));
189 /*****************************************************************************
191 * ntpsnmpd_cut_string
193 * This function will parse a given NULL terminated string and cut it
194 * into fields using the specified delimiter character.
195 * It will then copy the requested field into a destination buffer
196 * Example:
197 * ntpsnmpd_cut_string(read:my:lips:fool, RESULT, ':', 2, sizeof(RESULT))
198 * will copy "lips" to RESULT.
199 ****************************************************************************
200 * Parameters:
201 * src char* The name of the source string variable
202 * NOTE: must be NULL terminated!
203 * dest char* The name of the string which takes the
204 * requested field content
205 * delim char The delimiter character
206 * fieldnumber int The number of the required field
207 * (start counting with 0)
208 * maxsize int The maximum size of dest
210 * Returns:
211 * int length of resulting dest string
212 ****************************************************************************/
214 int ntpsnmpd_cut_string(char *src, char *dest, const char delim, int fieldnumber, int maxsize)
216 char string[2048];
217 int i = 0;
218 int j = 0;
219 int l = 0;
220 int a = 0;
222 strncpy (string, src, sizeof(string));
224 a = strlen(string);
226 memset (dest, 0, maxsize);
228 /* Parsing the field name */
229 for (i=0;l<=fieldnumber;i++)
231 if (i>=a)
232 l=fieldnumber+1; /* terminate loop */
233 else
235 if ( string[i] == delim )
237 l++; /* next field */
239 else if ( ( l == fieldnumber) && ( j < maxsize ) )
241 dest[j++]=string[i];
247 return (strlen(dest));
252 /*****************************************************************************
254 * read_ntp_value
256 * This function retrieves the value for a given variable, currently
257 * this only supports sysvars. It starts a full mode 6 send/receive/parse
258 * iteration and needs to be optimized, e.g. by using a caching mechanism
260 ****************************************************************************
261 * Parameters:
262 * variable char* The name of the required variable
263 * rbuffer char* The buffer where the value goes
264 * maxlength int Max. number of bytes for resultbuf
266 * Returns:
267 * u_int number of chars that have been copied to
268 * rbuffer
269 ****************************************************************************/
271 unsigned int read_ntp_value(char *variable, char *rbuffer, unsigned int maxlength)
273 unsigned int i, sv_len = 0;
274 char sv_data[NTPQ_BUFLEN];
276 memset (sv_data,0, NTPQ_BUFLEN);
277 sv_len= ntpq_read_sysvars ( sv_data, NTPQ_BUFLEN );
279 if ( sv_len )
281 i=ntpq_getvar( sv_data, sv_len , variable, rbuffer, maxlength);
282 return i;
283 } else {
284 return 0;
290 /*****************************************************************************
292 * The get_xxx functions
294 * The following function calls are callback functions that will be
295 * used by the master agent process to retrieve a value for a requested
296 * MIB object.
298 ****************************************************************************/
301 int get_ntpEntSoftwareName (netsnmp_mib_handler *handler,
302 netsnmp_handler_registration *reginfo,
303 netsnmp_agent_request_info *reqinfo,
304 netsnmp_request_info *requests)
306 char ntp_softwarename[NTPQ_BUFLEN];
308 memset (ntp_softwarename, 0, NTPQ_BUFLEN);
310 switch (reqinfo->mode) {
311 case MODE_GET:
313 if ( read_ntp_value("product", ntpvalue, NTPQ_BUFLEN) )
315 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
316 (u_char *)ntpvalue,
317 strlen(ntpvalue)
320 else if ( read_ntp_value("version", ntpvalue, NTPQ_BUFLEN) )
322 ntpsnmpd_cut_string(ntpvalue, ntp_softwarename, ' ', 0, sizeof(ntp_softwarename)-1);
323 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
324 (u_char *)ntp_softwarename,
325 strlen(ntp_softwarename)
327 } else {
328 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
329 (u_char *)"N/A",
333 break;
338 default:
339 /* If we cannot get the information we need, we will return a generic error to the SNMP client */
340 return SNMP_ERR_GENERR;
343 return SNMP_ERR_NOERROR;
347 int get_ntpEntSoftwareVersion (netsnmp_mib_handler *handler,
348 netsnmp_handler_registration *reginfo,
349 netsnmp_agent_request_info *reqinfo,
350 netsnmp_request_info *requests)
353 switch (reqinfo->mode) {
354 case MODE_GET:
357 if ( read_ntp_value("version", ntpvalue, NTPQ_BUFLEN) )
359 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
360 (u_char *)ntpvalue,
361 strlen(ntpvalue)
363 } else {
364 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
365 (u_char *)"N/A",
369 break;
374 default:
375 /* If we cannot get the information we need, we will return a generic error to the SNMP client */
376 return SNMP_ERR_GENERR;
379 return SNMP_ERR_NOERROR;
383 int get_ntpEntSoftwareVersionVal (netsnmp_mib_handler *handler,
384 netsnmp_handler_registration *reginfo,
385 netsnmp_agent_request_info *reqinfo,
386 netsnmp_request_info *requests)
388 unsigned int i = 0;
389 switch (reqinfo->mode) {
390 case MODE_GET:
393 if ( read_ntp_value("versionval", ntpvalue, NTPQ_BUFLEN) )
395 i=atoi(ntpvalue);
396 snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED,
397 (u_char *) &i,
398 sizeof (i)
400 } else {
401 i = 0;
402 snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED,
403 (u_char *) &i,
404 sizeof(i)
407 break;
412 default:
413 /* If we cannot get the information we need, we will return a generic error to the SNMP client */
414 return SNMP_ERR_GENERR;
417 return SNMP_ERR_NOERROR;
422 int get_ntpEntSoftwareVendor (netsnmp_mib_handler *handler,
423 netsnmp_handler_registration *reginfo,
424 netsnmp_agent_request_info *reqinfo,
425 netsnmp_request_info *requests)
428 switch (reqinfo->mode) {
429 case MODE_GET:
432 if ( read_ntp_value("vendor", ntpvalue, NTPQ_BUFLEN) )
434 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
435 (u_char *)ntpvalue,
436 strlen(ntpvalue)
438 } else {
439 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
440 (u_char *)"N/A",
444 break;
446 default:
447 /* If we cannot get the information we need, we will return a generic error to the SNMP client */
448 return SNMP_ERR_GENERR;
451 return SNMP_ERR_NOERROR;
455 int get_ntpEntSystemType (netsnmp_mib_handler *handler,
456 netsnmp_handler_registration *reginfo,
457 netsnmp_agent_request_info *reqinfo,
458 netsnmp_request_info *requests)
461 switch (reqinfo->mode) {
462 case MODE_GET:
465 if ( read_ntp_value("systemtype", ntpvalue, NTPQ_BUFLEN) )
467 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
468 (u_char *)ntpvalue,
469 strlen(ntpvalue)
473 if ( read_ntp_value("system", ntpvalue, NTPQ_BUFLEN) )
475 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
476 (u_char *)ntpvalue,
477 strlen(ntpvalue)
479 } else {
480 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
481 (u_char *)"N/A",
485 break;
490 default:
491 /* If we cannot get the information we need, we will return a generic error to the SNMP client */
492 return SNMP_ERR_GENERR;
495 return SNMP_ERR_NOERROR;
498 int get_ntpEntTimeResolution (netsnmp_mib_handler *handler,
499 netsnmp_handler_registration *reginfo,
500 netsnmp_agent_request_info *reqinfo,
501 netsnmp_request_info *requests)
504 switch (reqinfo->mode) {
505 case MODE_GET:
508 if ( read_ntp_value("resolution", ntpvalue, NTPQ_BUFLEN) )
510 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
511 (u_char *)ntpvalue,
512 strlen(ntpvalue)
514 } else {
515 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
516 (u_char *)"N/A",
520 break;
525 default:
526 /* If we cannot get the information we need, we will return a generic error to the SNMP client */
527 return SNMP_ERR_GENERR;
530 return SNMP_ERR_NOERROR;
534 int get_ntpEntTimeResolutionVal (netsnmp_mib_handler *handler,
535 netsnmp_handler_registration *reginfo,
536 netsnmp_agent_request_info *reqinfo,
537 netsnmp_request_info *requests)
540 unsigned int i = 0;
541 switch (reqinfo->mode) {
542 case MODE_GET:
545 if ( read_ntp_value("resolutionval", ntpvalue, NTPQ_BUFLEN) )
547 i=atoi(ntpvalue);
548 snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED,
549 (u_char *) &i,
550 sizeof (i)
552 } else {
553 i = 0;
554 snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED,
555 (u_char *) &i,
556 sizeof(i)
559 break;
564 default:
565 /* If we cannot get the information we need, we will return a generic error to the SNMP client */
566 return SNMP_ERR_GENERR;
569 return SNMP_ERR_NOERROR;
573 int get_ntpEntTimePrecision (netsnmp_mib_handler *handler,
574 netsnmp_handler_registration *reginfo,
575 netsnmp_agent_request_info *reqinfo,
576 netsnmp_request_info *requests)
578 switch (reqinfo->mode) {
579 case MODE_GET:
582 if ( read_ntp_value("precision", ntpvalue, NTPQ_BUFLEN) )
584 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
585 (u_char *)ntpvalue,
586 strlen(ntpvalue)
588 } else {
589 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
590 (u_char *)"N/A",
594 break;
599 default:
600 /* If we cannot get the information we need, we will return a generic error to the SNMP client */
601 return SNMP_ERR_GENERR;
604 return SNMP_ERR_NOERROR;
607 int get_ntpEntTimePrecisionVal (netsnmp_mib_handler *handler,
608 netsnmp_handler_registration *reginfo,
609 netsnmp_agent_request_info *reqinfo,
610 netsnmp_request_info *requests)
613 int i = 0;
614 switch (reqinfo->mode) {
615 case MODE_GET:
618 if ( read_ntp_value("precision", ntpvalue, NTPQ_BUFLEN) )
620 i=atoi(ntpvalue);
621 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
622 (u_char *) &i,
623 sizeof (i)
625 } else {
626 i = 0;
627 snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
628 (u_char *) &i,
629 sizeof(i)
632 break;
637 default:
638 /* If we cannot get the information we need, we will return a generic error to the SNMP client */
639 return SNMP_ERR_GENERR;
642 return SNMP_ERR_NOERROR;
647 int get_ntpEntTimeDistance (netsnmp_mib_handler *handler,
648 netsnmp_handler_registration *reginfo,
649 netsnmp_agent_request_info *reqinfo,
650 netsnmp_request_info *requests)
652 switch (reqinfo->mode) {
653 case MODE_GET:
656 if ( read_ntp_value("rootdelay", ntpvalue, NTPQ_BUFLEN) )
658 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
659 (u_char *)ntpvalue,
660 strlen(ntpvalue)
662 } else {
663 snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
664 (u_char *)"N/A",
668 break;
673 default:
674 /* If we cannot get the information we need, we will return a generic error to the SNMP client */
675 return SNMP_ERR_GENERR;
678 return SNMP_ERR_NOERROR;
684 * Initialize sub agent
685 * TODO: Define NTP MIB OID (has to be assigned by IANA)
686 * At the moment we use a private MIB branch (enterprises.5597.99)
689 void
690 init_ntpSnmpSubagentObject(void)
693 /* Register all MIB objects with the agentx master */
695 _SETUP_OID_RO( ntpEntSoftwareName , NTPV4_OID , 1, 1, 1, 0 );
696 _SETUP_OID_RO( ntpEntSoftwareVersion , NTPV4_OID , 1, 1, 2, 0 );
697 _SETUP_OID_RO( ntpEntSoftwareVersionVal , NTPV4_OID , 1, 1, 3, 0 );
698 _SETUP_OID_RO( ntpEntSoftwareVendor , NTPV4_OID , 1, 1, 4, 0 );
699 _SETUP_OID_RO( ntpEntSystemType , NTPV4_OID , 1, 1, 5, 0 );
700 _SETUP_OID_RO( ntpEntTimeResolution , NTPV4_OID , 1, 1, 6, 0 );
701 _SETUP_OID_RO( ntpEntTimeResolutionVal , NTPV4_OID , 1, 1, 7, 0 );
702 _SETUP_OID_RO( ntpEntTimePrecision , NTPV4_OID , 1, 1, 8, 0 );
703 _SETUP_OID_RO( ntpEntTimePrecisionVal , NTPV4_OID , 1, 1, 9, 0 );
704 _SETUP_OID_RO( ntpEntTimeDistance , NTPV4_OID , 1, 1,10, 0 );