1*2b15cb3dSCy Schubert /*****************************************************************************
2*2b15cb3dSCy Schubert *
3*2b15cb3dSCy Schubert * ntpSnmpSubAgentObject.c
4*2b15cb3dSCy Schubert *
5*2b15cb3dSCy Schubert * This file provides the callback functions for net-snmp and registers the
6*2b15cb3dSCy Schubert * serviced MIB objects with the master agent.
7*2b15cb3dSCy Schubert *
8*2b15cb3dSCy Schubert * Each object has its own callback function that is called by the
9*2b15cb3dSCy Schubert * master agent process whenever someone queries the corresponding MIB
10*2b15cb3dSCy Schubert * object.
11*2b15cb3dSCy Schubert *
12*2b15cb3dSCy Schubert * At the moment this triggers a full send/receive procedure for each
13*2b15cb3dSCy Schubert * queried MIB object, one of the things that are still on my todo list:
14*2b15cb3dSCy Schubert * a caching mechanism that reduces the number of requests sent to the
15*2b15cb3dSCy Schubert * ntpd process.
16*2b15cb3dSCy Schubert *
17*2b15cb3dSCy Schubert ****************************************************************************/
18*2b15cb3dSCy Schubert #include <ntp_snmp.h>
19*2b15cb3dSCy Schubert #include <ctype.h>
20*2b15cb3dSCy Schubert #include <ntp.h>
21*2b15cb3dSCy Schubert #include <libntpq.h>
22*2b15cb3dSCy Schubert
23*2b15cb3dSCy Schubert /* general purpose buffer length definition */
24*2b15cb3dSCy Schubert #define NTPQ_BUFLEN 2048
25*2b15cb3dSCy Schubert
26*2b15cb3dSCy Schubert char ntpvalue[NTPQ_BUFLEN];
27*2b15cb3dSCy Schubert
28*2b15cb3dSCy Schubert
29*2b15cb3dSCy Schubert /*****************************************************************************
30*2b15cb3dSCy Schubert *
31*2b15cb3dSCy Schubert * ntpsnmpd_parse_string
32*2b15cb3dSCy Schubert *
33*2b15cb3dSCy Schubert * This function will parse a given NULL terminated string and cut it
34*2b15cb3dSCy Schubert * into a fieldname and a value part (using the '=' as the delimiter.
35*2b15cb3dSCy Schubert * The fieldname will be converted to uppercase and all whitespace
36*2b15cb3dSCy Schubert * characters are removed from it.
37*2b15cb3dSCy Schubert * The value part is stripped, e.g. all whitespace characters are removed
38*2b15cb3dSCy Schubert * from the beginning and end of the string.
39*2b15cb3dSCy Schubert * If the value is started and ended with quotes ("), they will be removed
40*2b15cb3dSCy Schubert * and everything between the quotes is left untouched (including
41*2b15cb3dSCy Schubert * whitespace)
42*2b15cb3dSCy Schubert * Example:
43*2b15cb3dSCy Schubert * server host name = hello world!
44*2b15cb3dSCy Schubert * will result in a field string "SERVERHOSTNAME" and a value
45*2b15cb3dSCy Schubert * of "hello world!".
46*2b15cb3dSCy Schubert * My first Parameter = " is this! "
47*2b15cb3dSCy Schubert * results in a field string "MYFIRSTPARAMETER" and a value " is this! "
48*2b15cb3dSCy Schubert ****************************************************************************
49*2b15cb3dSCy Schubert * Parameters:
50*2b15cb3dSCy Schubert * string const char * The source string to parse.
51*2b15cb3dSCy Schubert * NOTE: must be NULL terminated!
52*2b15cb3dSCy Schubert * field char * The buffer for the field name.
53*2b15cb3dSCy Schubert * fieldsize size_t The size of the field buffer.
54*2b15cb3dSCy Schubert * value char * The buffer for the value.
55*2b15cb3dSCy Schubert * valuesize size_t The size of the value buffer.
56*2b15cb3dSCy Schubert *
57*2b15cb3dSCy Schubert * Returns:
58*2b15cb3dSCy Schubert * size_t length of value string
59*2b15cb3dSCy Schubert ****************************************************************************/
60*2b15cb3dSCy Schubert
61*2b15cb3dSCy Schubert size_t
ntpsnmpd_parse_string(const char * string,char * field,size_t fieldsize,char * value,size_t valuesize)62*2b15cb3dSCy Schubert ntpsnmpd_parse_string(
63*2b15cb3dSCy Schubert const char * string,
64*2b15cb3dSCy Schubert char * field,
65*2b15cb3dSCy Schubert size_t fieldsize,
66*2b15cb3dSCy Schubert char * value,
67*2b15cb3dSCy Schubert size_t valuesize
68*2b15cb3dSCy Schubert )
69*2b15cb3dSCy Schubert {
70*2b15cb3dSCy Schubert int i;
71*2b15cb3dSCy Schubert int j;
72*2b15cb3dSCy Schubert int loop;
73*2b15cb3dSCy Schubert size_t str_cnt;
74*2b15cb3dSCy Schubert size_t val_cnt;
75*2b15cb3dSCy Schubert
76*2b15cb3dSCy Schubert /* we need at least one byte to work with to simplify */
77*2b15cb3dSCy Schubert if (fieldsize < 1 || valuesize < 1)
78*2b15cb3dSCy Schubert return 0;
79*2b15cb3dSCy Schubert
80*2b15cb3dSCy Schubert str_cnt = strlen(string);
81*2b15cb3dSCy Schubert
82*2b15cb3dSCy Schubert /* Parsing the field name */
83*2b15cb3dSCy Schubert j = 0;
84*2b15cb3dSCy Schubert loop = TRUE;
85*2b15cb3dSCy Schubert for (i = 0; loop && i <= str_cnt; i++) {
86*2b15cb3dSCy Schubert switch (string[i]) {
87*2b15cb3dSCy Schubert
88*2b15cb3dSCy Schubert case '\t': /* Tab */
89*2b15cb3dSCy Schubert case '\n': /* LF */
90*2b15cb3dSCy Schubert case '\r': /* CR */
91*2b15cb3dSCy Schubert case ' ': /* Space */
92*2b15cb3dSCy Schubert break;
93*2b15cb3dSCy Schubert
94*2b15cb3dSCy Schubert case '=':
95*2b15cb3dSCy Schubert loop = FALSE;
96*2b15cb3dSCy Schubert break;
97*2b15cb3dSCy Schubert
98*2b15cb3dSCy Schubert default:
99*2b15cb3dSCy Schubert if (j < fieldsize)
100*2b15cb3dSCy Schubert field[j++] = toupper(string[i]);
101*2b15cb3dSCy Schubert }
102*2b15cb3dSCy Schubert }
103*2b15cb3dSCy Schubert
104*2b15cb3dSCy Schubert j = min(j, fieldsize - 1);
105*2b15cb3dSCy Schubert field[j] = '\0';
106*2b15cb3dSCy Schubert
107*2b15cb3dSCy Schubert /* Now parsing the value */
108*2b15cb3dSCy Schubert value[0] = '\0';
109*2b15cb3dSCy Schubert j = 0;
110*2b15cb3dSCy Schubert for (val_cnt = 0; i < str_cnt; i++) {
111*2b15cb3dSCy Schubert if (string[i] > 0x0D && string[i] != ' ')
112*2b15cb3dSCy Schubert val_cnt = min(j + 1, valuesize - 1);
113*2b15cb3dSCy Schubert
114*2b15cb3dSCy Schubert if (value[0] != '\0' ||
115*2b15cb3dSCy Schubert (string[i] > 0x0D && string[i] != ' ')) {
116*2b15cb3dSCy Schubert if (j < valuesize)
117*2b15cb3dSCy Schubert value[j++] = string[i];
118*2b15cb3dSCy Schubert }
119*2b15cb3dSCy Schubert }
120*2b15cb3dSCy Schubert value[val_cnt] = '\0';
121*2b15cb3dSCy Schubert
122*2b15cb3dSCy Schubert if (value[0] == '"') {
123*2b15cb3dSCy Schubert val_cnt--;
124*2b15cb3dSCy Schubert strlcpy(value, &value[1], valuesize);
125*2b15cb3dSCy Schubert if (val_cnt > 0 && value[val_cnt - 1] == '"') {
126*2b15cb3dSCy Schubert val_cnt--;
127*2b15cb3dSCy Schubert value[val_cnt] = '\0';
128*2b15cb3dSCy Schubert }
129*2b15cb3dSCy Schubert }
130*2b15cb3dSCy Schubert
131*2b15cb3dSCy Schubert return val_cnt;
132*2b15cb3dSCy Schubert }
133*2b15cb3dSCy Schubert
134*2b15cb3dSCy Schubert
135*2b15cb3dSCy Schubert /*****************************************************************************
136*2b15cb3dSCy Schubert *
137*2b15cb3dSCy Schubert * ntpsnmpd_cut_string
138*2b15cb3dSCy Schubert *
139*2b15cb3dSCy Schubert * This function will parse a given NULL terminated string and cut it
140*2b15cb3dSCy Schubert * into fields using the specified delimiter character.
141*2b15cb3dSCy Schubert * It will then copy the requested field into a destination buffer
142*2b15cb3dSCy Schubert * Example:
143*2b15cb3dSCy Schubert * ntpsnmpd_cut_string(read:my:lips:fool, RESULT, ':', 2, sizeof(RESULT))
144*2b15cb3dSCy Schubert * will copy "lips" to RESULT.
145*2b15cb3dSCy Schubert ****************************************************************************
146*2b15cb3dSCy Schubert * Parameters:
147*2b15cb3dSCy Schubert * src const char * The name of the source string variable
148*2b15cb3dSCy Schubert * NOTE: must be NULL terminated!
149*2b15cb3dSCy Schubert * dest char * The name of the string which takes the
150*2b15cb3dSCy Schubert * requested field content
151*2b15cb3dSCy Schubert * delim char The delimiter character
152*2b15cb3dSCy Schubert * fieldnumber int The number of the required field
153*2b15cb3dSCy Schubert * (start counting with 0)
154*2b15cb3dSCy Schubert * maxsize size_t The maximum size of dest
155*2b15cb3dSCy Schubert *
156*2b15cb3dSCy Schubert * Returns:
157*2b15cb3dSCy Schubert * size_t length of resulting dest string
158*2b15cb3dSCy Schubert ****************************************************************************/
159*2b15cb3dSCy Schubert
160*2b15cb3dSCy Schubert size_t
ntpsnmpd_cut_string(const char * string,char * dest,char delim,int fieldnumber,size_t maxsize)161*2b15cb3dSCy Schubert ntpsnmpd_cut_string(
162*2b15cb3dSCy Schubert const char * string,
163*2b15cb3dSCy Schubert char * dest,
164*2b15cb3dSCy Schubert char delim,
165*2b15cb3dSCy Schubert int fieldnumber,
166*2b15cb3dSCy Schubert size_t maxsize
167*2b15cb3dSCy Schubert )
168*2b15cb3dSCy Schubert {
169*2b15cb3dSCy Schubert size_t i;
170*2b15cb3dSCy Schubert size_t j;
171*2b15cb3dSCy Schubert int l;
172*2b15cb3dSCy Schubert size_t str_cnt;
173*2b15cb3dSCy Schubert
174*2b15cb3dSCy Schubert if (maxsize < 1)
175*2b15cb3dSCy Schubert return 0;
176*2b15cb3dSCy Schubert
177*2b15cb3dSCy Schubert str_cnt = strlen(string);
178*2b15cb3dSCy Schubert j = 0;
179*2b15cb3dSCy Schubert memset(dest, 0, maxsize);
180*2b15cb3dSCy Schubert
181*2b15cb3dSCy Schubert /* Parsing the field name */
182*2b15cb3dSCy Schubert for (i = 0, l = 0; i < str_cnt && l <= fieldnumber; i++) {
183*2b15cb3dSCy Schubert if (string[i] == delim)
184*2b15cb3dSCy Schubert l++; /* next field */
185*2b15cb3dSCy Schubert else if (l == fieldnumber && j < maxsize)
186*2b15cb3dSCy Schubert dest[j++] = string[i];
187*2b15cb3dSCy Schubert }
188*2b15cb3dSCy Schubert j = min(j, maxsize - 1);
189*2b15cb3dSCy Schubert dest[j] = '\0';
190*2b15cb3dSCy Schubert
191*2b15cb3dSCy Schubert return j;
192*2b15cb3dSCy Schubert }
193*2b15cb3dSCy Schubert
194*2b15cb3dSCy Schubert
195*2b15cb3dSCy Schubert /*****************************************************************************
196*2b15cb3dSCy Schubert *
197*2b15cb3dSCy Schubert * read_ntp_value
198*2b15cb3dSCy Schubert *
199*2b15cb3dSCy Schubert * This function retrieves the value for a given variable, currently
200*2b15cb3dSCy Schubert * this only supports sysvars. It starts a full mode 6 send/receive/parse
201*2b15cb3dSCy Schubert * iteration and needs to be optimized, e.g. by using a caching mechanism
202*2b15cb3dSCy Schubert *
203*2b15cb3dSCy Schubert ****************************************************************************
204*2b15cb3dSCy Schubert * Parameters:
205*2b15cb3dSCy Schubert * variable char* The name of the required variable
206*2b15cb3dSCy Schubert * rbuffer char* The buffer where the value goes
207*2b15cb3dSCy Schubert * maxlength int Max. number of bytes for resultbuf
208*2b15cb3dSCy Schubert *
209*2b15cb3dSCy Schubert * Returns:
210*2b15cb3dSCy Schubert * u_int number of chars that have been copied to
211*2b15cb3dSCy Schubert * rbuffer
212*2b15cb3dSCy Schubert ****************************************************************************/
213*2b15cb3dSCy Schubert
214*2b15cb3dSCy Schubert size_t
read_ntp_value(const char * variable,char * value,size_t valuesize)215*2b15cb3dSCy Schubert read_ntp_value(
216*2b15cb3dSCy Schubert const char * variable,
217*2b15cb3dSCy Schubert char * value,
218*2b15cb3dSCy Schubert size_t valuesize
219*2b15cb3dSCy Schubert )
220*2b15cb3dSCy Schubert {
221*2b15cb3dSCy Schubert size_t sv_len;
222*2b15cb3dSCy Schubert char sv_data[NTPQ_BUFLEN];
223*2b15cb3dSCy Schubert
224*2b15cb3dSCy Schubert memset(sv_data, 0, sizeof(sv_data));
225*2b15cb3dSCy Schubert sv_len = ntpq_read_sysvars(sv_data, sizeof(sv_data));
226*2b15cb3dSCy Schubert
227*2b15cb3dSCy Schubert if (0 == sv_len)
228*2b15cb3dSCy Schubert return 0;
229*2b15cb3dSCy Schubert else
230*2b15cb3dSCy Schubert return ntpq_getvar(sv_data, sv_len, variable, value,
231*2b15cb3dSCy Schubert valuesize);
232*2b15cb3dSCy Schubert }
233*2b15cb3dSCy Schubert
234*2b15cb3dSCy Schubert
235*2b15cb3dSCy Schubert /*****************************************************************************
236*2b15cb3dSCy Schubert *
237*2b15cb3dSCy Schubert * The get_xxx functions
238*2b15cb3dSCy Schubert *
239*2b15cb3dSCy Schubert * The following function calls are callback functions that will be
240*2b15cb3dSCy Schubert * used by the master agent process to retrieve a value for a requested
241*2b15cb3dSCy Schubert * MIB object.
242*2b15cb3dSCy Schubert *
243*2b15cb3dSCy Schubert ****************************************************************************/
244*2b15cb3dSCy Schubert
245*2b15cb3dSCy Schubert
get_ntpEntSoftwareName(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * reqinfo,netsnmp_request_info * requests)246*2b15cb3dSCy Schubert int get_ntpEntSoftwareName (netsnmp_mib_handler *handler,
247*2b15cb3dSCy Schubert netsnmp_handler_registration *reginfo,
248*2b15cb3dSCy Schubert netsnmp_agent_request_info *reqinfo,
249*2b15cb3dSCy Schubert netsnmp_request_info *requests)
250*2b15cb3dSCy Schubert {
251*2b15cb3dSCy Schubert char ntp_softwarename[NTPQ_BUFLEN];
252*2b15cb3dSCy Schubert
253*2b15cb3dSCy Schubert memset (ntp_softwarename, 0, NTPQ_BUFLEN);
254*2b15cb3dSCy Schubert
255*2b15cb3dSCy Schubert switch (reqinfo->mode) {
256*2b15cb3dSCy Schubert case MODE_GET:
257*2b15cb3dSCy Schubert {
258*2b15cb3dSCy Schubert if ( read_ntp_value("product", ntpvalue, NTPQ_BUFLEN) )
259*2b15cb3dSCy Schubert {
260*2b15cb3dSCy Schubert snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
261*2b15cb3dSCy Schubert (u_char *)ntpvalue,
262*2b15cb3dSCy Schubert strlen(ntpvalue)
263*2b15cb3dSCy Schubert );
264*2b15cb3dSCy Schubert }
265*2b15cb3dSCy Schubert else if ( read_ntp_value("version", ntpvalue, NTPQ_BUFLEN) )
266*2b15cb3dSCy Schubert {
267*2b15cb3dSCy Schubert ntpsnmpd_cut_string(ntpvalue, ntp_softwarename, ' ', 0, sizeof(ntp_softwarename)-1);
268*2b15cb3dSCy Schubert snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
269*2b15cb3dSCy Schubert (u_char *)ntp_softwarename,
270*2b15cb3dSCy Schubert strlen(ntp_softwarename)
271*2b15cb3dSCy Schubert );
272*2b15cb3dSCy Schubert } else {
273*2b15cb3dSCy Schubert snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
274*2b15cb3dSCy Schubert (u_char *)"N/A",
275*2b15cb3dSCy Schubert 3
276*2b15cb3dSCy Schubert );
277*2b15cb3dSCy Schubert }
278*2b15cb3dSCy Schubert break;
279*2b15cb3dSCy Schubert
280*2b15cb3dSCy Schubert }
281*2b15cb3dSCy Schubert
282*2b15cb3dSCy Schubert
283*2b15cb3dSCy Schubert default:
284*2b15cb3dSCy Schubert /* If we cannot get the information we need, we will return a generic error to the SNMP client */
285*2b15cb3dSCy Schubert return SNMP_ERR_GENERR;
286*2b15cb3dSCy Schubert }
287*2b15cb3dSCy Schubert
288*2b15cb3dSCy Schubert return SNMP_ERR_NOERROR;
289*2b15cb3dSCy Schubert }
290*2b15cb3dSCy Schubert
291*2b15cb3dSCy Schubert
get_ntpEntSoftwareVersion(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * reqinfo,netsnmp_request_info * requests)292*2b15cb3dSCy Schubert int get_ntpEntSoftwareVersion (netsnmp_mib_handler *handler,
293*2b15cb3dSCy Schubert netsnmp_handler_registration *reginfo,
294*2b15cb3dSCy Schubert netsnmp_agent_request_info *reqinfo,
295*2b15cb3dSCy Schubert netsnmp_request_info *requests)
296*2b15cb3dSCy Schubert {
297*2b15cb3dSCy Schubert
298*2b15cb3dSCy Schubert switch (reqinfo->mode) {
299*2b15cb3dSCy Schubert case MODE_GET:
300*2b15cb3dSCy Schubert {
301*2b15cb3dSCy Schubert
302*2b15cb3dSCy Schubert if ( read_ntp_value("version", ntpvalue, NTPQ_BUFLEN) )
303*2b15cb3dSCy Schubert {
304*2b15cb3dSCy Schubert snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
305*2b15cb3dSCy Schubert (u_char *)ntpvalue,
306*2b15cb3dSCy Schubert strlen(ntpvalue)
307*2b15cb3dSCy Schubert );
308*2b15cb3dSCy Schubert } else {
309*2b15cb3dSCy Schubert snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
310*2b15cb3dSCy Schubert (u_char *)"N/A",
311*2b15cb3dSCy Schubert 3
312*2b15cb3dSCy Schubert );
313*2b15cb3dSCy Schubert }
314*2b15cb3dSCy Schubert break;
315*2b15cb3dSCy Schubert
316*2b15cb3dSCy Schubert }
317*2b15cb3dSCy Schubert
318*2b15cb3dSCy Schubert
319*2b15cb3dSCy Schubert default:
320*2b15cb3dSCy Schubert /* If we cannot get the information we need, we will return a generic error to the SNMP client */
321*2b15cb3dSCy Schubert return SNMP_ERR_GENERR;
322*2b15cb3dSCy Schubert }
323*2b15cb3dSCy Schubert
324*2b15cb3dSCy Schubert return SNMP_ERR_NOERROR;
325*2b15cb3dSCy Schubert }
326*2b15cb3dSCy Schubert
327*2b15cb3dSCy Schubert
get_ntpEntSoftwareVendor(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * reqinfo,netsnmp_request_info * requests)328*2b15cb3dSCy Schubert int get_ntpEntSoftwareVendor (netsnmp_mib_handler *handler,
329*2b15cb3dSCy Schubert netsnmp_handler_registration *reginfo,
330*2b15cb3dSCy Schubert netsnmp_agent_request_info *reqinfo,
331*2b15cb3dSCy Schubert netsnmp_request_info *requests)
332*2b15cb3dSCy Schubert {
333*2b15cb3dSCy Schubert
334*2b15cb3dSCy Schubert switch (reqinfo->mode) {
335*2b15cb3dSCy Schubert case MODE_GET:
336*2b15cb3dSCy Schubert {
337*2b15cb3dSCy Schubert
338*2b15cb3dSCy Schubert if ( read_ntp_value("vendor", ntpvalue, NTPQ_BUFLEN) )
339*2b15cb3dSCy Schubert {
340*2b15cb3dSCy Schubert snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
341*2b15cb3dSCy Schubert (u_char *)ntpvalue,
342*2b15cb3dSCy Schubert strlen(ntpvalue)
343*2b15cb3dSCy Schubert );
344*2b15cb3dSCy Schubert } else {
345*2b15cb3dSCy Schubert snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
346*2b15cb3dSCy Schubert (u_char *)"N/A",
347*2b15cb3dSCy Schubert 3
348*2b15cb3dSCy Schubert );
349*2b15cb3dSCy Schubert }
350*2b15cb3dSCy Schubert break;
351*2b15cb3dSCy Schubert
352*2b15cb3dSCy Schubert default:
353*2b15cb3dSCy Schubert /* If we cannot get the information we need, we will return a generic error to the SNMP client */
354*2b15cb3dSCy Schubert return SNMP_ERR_GENERR;
355*2b15cb3dSCy Schubert }
356*2b15cb3dSCy Schubert }
357*2b15cb3dSCy Schubert return SNMP_ERR_NOERROR;
358*2b15cb3dSCy Schubert }
359*2b15cb3dSCy Schubert
360*2b15cb3dSCy Schubert
get_ntpEntSystemType(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * reqinfo,netsnmp_request_info * requests)361*2b15cb3dSCy Schubert int get_ntpEntSystemType (netsnmp_mib_handler *handler,
362*2b15cb3dSCy Schubert netsnmp_handler_registration *reginfo,
363*2b15cb3dSCy Schubert netsnmp_agent_request_info *reqinfo,
364*2b15cb3dSCy Schubert netsnmp_request_info *requests)
365*2b15cb3dSCy Schubert {
366*2b15cb3dSCy Schubert
367*2b15cb3dSCy Schubert switch (reqinfo->mode) {
368*2b15cb3dSCy Schubert case MODE_GET:
369*2b15cb3dSCy Schubert {
370*2b15cb3dSCy Schubert
371*2b15cb3dSCy Schubert if ( read_ntp_value("systemtype", ntpvalue, NTPQ_BUFLEN) )
372*2b15cb3dSCy Schubert {
373*2b15cb3dSCy Schubert snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
374*2b15cb3dSCy Schubert (u_char *)ntpvalue,
375*2b15cb3dSCy Schubert strlen(ntpvalue)
376*2b15cb3dSCy Schubert );
377*2b15cb3dSCy Schubert }
378*2b15cb3dSCy Schubert
379*2b15cb3dSCy Schubert if ( read_ntp_value("system", ntpvalue, NTPQ_BUFLEN) )
380*2b15cb3dSCy Schubert {
381*2b15cb3dSCy Schubert snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
382*2b15cb3dSCy Schubert (u_char *)ntpvalue,
383*2b15cb3dSCy Schubert strlen(ntpvalue)
384*2b15cb3dSCy Schubert );
385*2b15cb3dSCy Schubert } else {
386*2b15cb3dSCy Schubert snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
387*2b15cb3dSCy Schubert (u_char *)"N/A",
388*2b15cb3dSCy Schubert 3
389*2b15cb3dSCy Schubert );
390*2b15cb3dSCy Schubert }
391*2b15cb3dSCy Schubert break;
392*2b15cb3dSCy Schubert
393*2b15cb3dSCy Schubert }
394*2b15cb3dSCy Schubert
395*2b15cb3dSCy Schubert
396*2b15cb3dSCy Schubert default:
397*2b15cb3dSCy Schubert /* If we cannot get the information we need, we will return a generic error to the SNMP client */
398*2b15cb3dSCy Schubert return SNMP_ERR_GENERR;
399*2b15cb3dSCy Schubert }
400*2b15cb3dSCy Schubert
401*2b15cb3dSCy Schubert return SNMP_ERR_NOERROR;
402*2b15cb3dSCy Schubert }
403*2b15cb3dSCy Schubert
404*2b15cb3dSCy Schubert
405*2b15cb3dSCy Schubert /*
406*2b15cb3dSCy Schubert * ntpEntTimeResolution
407*2b15cb3dSCy Schubert * "The time resolution in integer format, where the resolution
408*2b15cb3dSCy Schubert * is represented as divisions of a second, e.g., a value of 1000
409*2b15cb3dSCy Schubert * translates to 1.0 ms."
410*2b15cb3dSCy Schubert *
411*2b15cb3dSCy Schubert * ntpEntTimeResolution is a challenge for ntpd, as the resolution is
412*2b15cb3dSCy Schubert * not known nor exposed by ntpd, only the measured precision (time to
413*2b15cb3dSCy Schubert * read the clock).
414*2b15cb3dSCy Schubert *
415*2b15cb3dSCy Schubert * Logically the resolution must be at least the precision, so report
416*2b15cb3dSCy Schubert * it as our best approximation of resolution until/unless ntpd provides
417*2b15cb3dSCy Schubert * better.
418*2b15cb3dSCy Schubert */
419*2b15cb3dSCy Schubert int
get_ntpEntTimeResolution(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * reqinfo,netsnmp_request_info * requests)420*2b15cb3dSCy Schubert get_ntpEntTimeResolution(
421*2b15cb3dSCy Schubert netsnmp_mib_handler * handler,
422*2b15cb3dSCy Schubert netsnmp_handler_registration * reginfo,
423*2b15cb3dSCy Schubert netsnmp_agent_request_info * reqinfo,
424*2b15cb3dSCy Schubert netsnmp_request_info * requests
425*2b15cb3dSCy Schubert )
426*2b15cb3dSCy Schubert {
427*2b15cb3dSCy Schubert int precision;
428*2b15cb3dSCy Schubert u_int32 resolution;
429*2b15cb3dSCy Schubert
430*2b15cb3dSCy Schubert switch (reqinfo->mode) {
431*2b15cb3dSCy Schubert
432*2b15cb3dSCy Schubert case MODE_GET:
433*2b15cb3dSCy Schubert if (!read_ntp_value("precision", ntpvalue,
434*2b15cb3dSCy Schubert sizeof(ntpvalue)))
435*2b15cb3dSCy Schubert return SNMP_ERR_GENERR;
436*2b15cb3dSCy Schubert if (1 != sscanf(ntpvalue, "%d", &precision))
437*2b15cb3dSCy Schubert return SNMP_ERR_GENERR;
438*2b15cb3dSCy Schubert if (precision >= 0)
439*2b15cb3dSCy Schubert return SNMP_ERR_GENERR;
440*2b15cb3dSCy Schubert precision = max(precision, -31);
441*2b15cb3dSCy Schubert resolution = 1 << -precision;
442*2b15cb3dSCy Schubert snmp_set_var_typed_value(
443*2b15cb3dSCy Schubert requests->requestvb,
444*2b15cb3dSCy Schubert ASN_UNSIGNED,
445*2b15cb3dSCy Schubert (void *)&resolution,
446*2b15cb3dSCy Schubert sizeof(resolution));
447*2b15cb3dSCy Schubert break;
448*2b15cb3dSCy Schubert
449*2b15cb3dSCy Schubert default:
450*2b15cb3dSCy Schubert return SNMP_ERR_GENERR;
451*2b15cb3dSCy Schubert }
452*2b15cb3dSCy Schubert
453*2b15cb3dSCy Schubert return SNMP_ERR_NOERROR;
454*2b15cb3dSCy Schubert }
455*2b15cb3dSCy Schubert
456*2b15cb3dSCy Schubert
457*2b15cb3dSCy Schubert /*
458*2b15cb3dSCy Schubert * ntpEntTimePrecision
459*2b15cb3dSCy Schubert * "The entity's precision in integer format, shows the precision.
460*2b15cb3dSCy Schubert * A value of -5 would mean 2^-5 = 31.25 ms."
461*2b15cb3dSCy Schubert */
462*2b15cb3dSCy Schubert int
get_ntpEntTimePrecision(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * reqinfo,netsnmp_request_info * requests)463*2b15cb3dSCy Schubert get_ntpEntTimePrecision(
464*2b15cb3dSCy Schubert netsnmp_mib_handler * handler,
465*2b15cb3dSCy Schubert netsnmp_handler_registration * reginfo,
466*2b15cb3dSCy Schubert netsnmp_agent_request_info * reqinfo,
467*2b15cb3dSCy Schubert netsnmp_request_info * requests
468*2b15cb3dSCy Schubert )
469*2b15cb3dSCy Schubert {
470*2b15cb3dSCy Schubert int precision;
471*2b15cb3dSCy Schubert int32 precision32;
472*2b15cb3dSCy Schubert
473*2b15cb3dSCy Schubert switch (reqinfo->mode) {
474*2b15cb3dSCy Schubert
475*2b15cb3dSCy Schubert case MODE_GET:
476*2b15cb3dSCy Schubert if (!read_ntp_value("precision", ntpvalue,
477*2b15cb3dSCy Schubert sizeof(ntpvalue)))
478*2b15cb3dSCy Schubert return SNMP_ERR_GENERR;
479*2b15cb3dSCy Schubert if (1 != sscanf(ntpvalue, "%d", &precision))
480*2b15cb3dSCy Schubert return SNMP_ERR_GENERR;
481*2b15cb3dSCy Schubert precision32 = (int32)precision;
482*2b15cb3dSCy Schubert snmp_set_var_typed_value(
483*2b15cb3dSCy Schubert requests->requestvb,
484*2b15cb3dSCy Schubert ASN_INTEGER,
485*2b15cb3dSCy Schubert (void *)&precision32,
486*2b15cb3dSCy Schubert sizeof(precision32));
487*2b15cb3dSCy Schubert break;
488*2b15cb3dSCy Schubert
489*2b15cb3dSCy Schubert default:
490*2b15cb3dSCy Schubert return SNMP_ERR_GENERR;
491*2b15cb3dSCy Schubert }
492*2b15cb3dSCy Schubert
493*2b15cb3dSCy Schubert return SNMP_ERR_NOERROR;
494*2b15cb3dSCy Schubert }
495*2b15cb3dSCy Schubert
496*2b15cb3dSCy Schubert
get_ntpEntTimeDistance(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * reqinfo,netsnmp_request_info * requests)497*2b15cb3dSCy Schubert int get_ntpEntTimeDistance (netsnmp_mib_handler *handler,
498*2b15cb3dSCy Schubert netsnmp_handler_registration *reginfo,
499*2b15cb3dSCy Schubert netsnmp_agent_request_info *reqinfo,
500*2b15cb3dSCy Schubert netsnmp_request_info *requests)
501*2b15cb3dSCy Schubert {
502*2b15cb3dSCy Schubert switch (reqinfo->mode) {
503*2b15cb3dSCy Schubert case MODE_GET:
504*2b15cb3dSCy Schubert {
505*2b15cb3dSCy Schubert
506*2b15cb3dSCy Schubert if ( read_ntp_value("rootdelay", ntpvalue, NTPQ_BUFLEN) )
507*2b15cb3dSCy Schubert {
508*2b15cb3dSCy Schubert snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
509*2b15cb3dSCy Schubert (u_char *)ntpvalue,
510*2b15cb3dSCy Schubert strlen(ntpvalue)
511*2b15cb3dSCy Schubert );
512*2b15cb3dSCy Schubert } else {
513*2b15cb3dSCy Schubert snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
514*2b15cb3dSCy Schubert (u_char *)"N/A",
515*2b15cb3dSCy Schubert 3
516*2b15cb3dSCy Schubert );
517*2b15cb3dSCy Schubert }
518*2b15cb3dSCy Schubert break;
519*2b15cb3dSCy Schubert
520*2b15cb3dSCy Schubert }
521*2b15cb3dSCy Schubert
522*2b15cb3dSCy Schubert
523*2b15cb3dSCy Schubert default:
524*2b15cb3dSCy Schubert /* If we cannot get the information we need, we will return a generic error to the SNMP client */
525*2b15cb3dSCy Schubert return SNMP_ERR_GENERR;
526*2b15cb3dSCy Schubert }
527*2b15cb3dSCy Schubert
528*2b15cb3dSCy Schubert return SNMP_ERR_NOERROR;
529*2b15cb3dSCy Schubert }
530*2b15cb3dSCy Schubert
531*2b15cb3dSCy Schubert
532*2b15cb3dSCy Schubert /*
533*2b15cb3dSCy Schubert *
534*2b15cb3dSCy Schubert * Initialize sub agent
535*2b15cb3dSCy Schubert */
536*2b15cb3dSCy Schubert
537*2b15cb3dSCy Schubert void
init_ntpSnmpSubagentObject(void)538*2b15cb3dSCy Schubert init_ntpSnmpSubagentObject(void)
539*2b15cb3dSCy Schubert {
540*2b15cb3dSCy Schubert /* Register all MIB objects with the agentx master */
541*2b15cb3dSCy Schubert NTP_OID_RO( ntpEntSoftwareName, 1, 1, 1, 0);
542*2b15cb3dSCy Schubert NTP_OID_RO( ntpEntSoftwareVersion, 1, 1, 2, 0);
543*2b15cb3dSCy Schubert NTP_OID_RO( ntpEntSoftwareVendor, 1, 1, 3, 0);
544*2b15cb3dSCy Schubert NTP_OID_RO( ntpEntSystemType, 1, 1, 4, 0);
545*2b15cb3dSCy Schubert NTP_OID_RO( ntpEntTimeResolution, 1, 1, 5, 0);
546*2b15cb3dSCy Schubert NTP_OID_RO( ntpEntTimePrecision, 1, 1, 6, 0);
547*2b15cb3dSCy Schubert NTP_OID_RO( ntpEntTimeDistance, 1, 1, 7, 0);
548*2b15cb3dSCy Schubert }
549*2b15cb3dSCy Schubert
550