xref: /freebsd-src/contrib/ntp/ntpsnmpd/ntpSnmpSubagentObject.c (revision 416ba5c74546f32a993436a99516d35008e9f384)
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