1290001Sglebius/*****************************************************************************
2290001Sglebius *
3290001Sglebius *  libntpq.c
4290001Sglebius *
5290001Sglebius *  This is the wrapper library for ntpq, the NTP query utility.
6290001Sglebius *  This library reuses the sourcecode from ntpq and exports a number
7290001Sglebius *  of useful functions in a library that can be linked against applications
8290001Sglebius *  that need to query the status of a running ntpd. The whole
9290001Sglebius *  communcation is based on mode 6 packets.
10290001Sglebius *
11290001Sglebius ****************************************************************************/
12290001Sglebius#define LIBNTPQ_C
13290001Sglebius#define NO_MAIN_ALLOWED 1
14290001Sglebius/* #define BUILD_AS_LIB		Already provided by the Makefile */
15290001Sglebius
16290001Sglebius#include "ntpq.c"
17290001Sglebius#include "libntpq.h"
18290001Sglebius
19290001Sglebius/* Function Prototypes */
20290001Sglebius
21290001Sglebius
22290001Sglebiusconst char *Version = "libntpq 0.3beta";
23290001Sglebius
24290001Sglebius/* global variables used for holding snapshots of data */
25290001Sglebiuschar peervars[NTPQ_BUFLEN];
26290001Sglebiusint peervarlen = 0;
27290001Sglebiusassocid_t peervar_assoc = 0;
28290001Sglebiuschar clockvars[NTPQ_BUFLEN];
29290001Sglebiusint clockvarlen = 0;
30290001Sglebiusint clockvar_assoc = 0;
31290001Sglebiuschar sysvars[NTPQ_BUFLEN];
32290001Sglebiusint sysvarlen = 0;
33290001Sglebiuschar *ntpq_resultbuffer[NTPQ_BUFLEN];
34290001Sglebiusunsigned short ntpq_associations[MAXASSOC];
35290001Sglebiusstruct ntpq_varlist ntpq_varlist[MAXLIST];
36290001Sglebius
37290001Sglebius/*****************************************************************************
38290001Sglebius *
39290001Sglebius *  ntpq_stripquotes
40290001Sglebius *
41290001Sglebius *  Parses a given character buffer srcbuf and removes all quoted
42290001Sglebius *  characters. The resulting string is copied to the specified
43290001Sglebius *  resultbuf character buffer.  E.g. \" will be translated into "
44290001Sglebius *
45290001Sglebius ****************************************************************************
46290001Sglebius * Parameters:
47290001Sglebius *	resultbuf	char*	The resulting string without quoted
48290001Sglebius *				characters
49290001Sglebius *	srcbuf		char*	The buffer holding the original string
50290001Sglebius *	datalen		int	The number of bytes stored in srcbuf
51290001Sglebius *	maxlen		int	Max. number of bytes for resultbuf
52290001Sglebius *
53290001Sglebius * Returns:
54290001Sglebius *	int		number of chars that have been copied to
55290001Sglebius *			resultbuf
56290001Sglebius ****************************************************************************/
57290001Sglebius
58290001Sglebiusint ntpq_stripquotes ( char *resultbuf, char *srcbuf, int datalen, int maxlen )
59290001Sglebius{
60290001Sglebius	char* tmpbuf = srcbuf;
61290001Sglebius
62290001Sglebius	while ( *tmpbuf != 0 )
63290001Sglebius	{
64290001Sglebius		if ( *tmpbuf == '\"' )
65290001Sglebius		{
66290001Sglebius			tmpbuf++;
67290001Sglebius			continue;
68290001Sglebius		}
69290001Sglebius
70290001Sglebius		if ( *tmpbuf == '\\' )
71290001Sglebius		{
72290001Sglebius			tmpbuf++;
73290001Sglebius			switch ( *tmpbuf )
74290001Sglebius			{
75290001Sglebius				/* ignore if end of string */
76290001Sglebius				case 0:
77290001Sglebius					continue;
78290001Sglebius				/* skip and do not copy */
79290001Sglebius				case '\"': /* quotes */
80290001Sglebius				case 'n': /*newline*/
81290001Sglebius				case 'r': /*carriage return*/
82290001Sglebius				case 'g': /*bell*/
83290001Sglebius				case 't': /*tab*/
84290001Sglebius					tmpbuf++;
85290001Sglebius					continue;
86290001Sglebius			}
87290001Sglebius		}
88290001Sglebius
89290001Sglebius		*resultbuf++ = *tmpbuf++;
90290001Sglebius
91290001Sglebius	}
92290001Sglebius
93290001Sglebius	*resultbuf = 0;
94290001Sglebius	return strlen(resultbuf);
95290001Sglebius}
96290001Sglebius
97290001Sglebius
98290001Sglebius/*****************************************************************************
99290001Sglebius *
100290001Sglebius *  ntpq_getvar
101290001Sglebius *
102290001Sglebius *  This function parses a given buffer for a variable/value pair and
103290001Sglebius *  copies the value of the requested variable into the specified
104290001Sglebius *  varvalue buffer.
105290001Sglebius *
106290001Sglebius *  It returns the number of bytes copied or zero for an empty result
107290001Sglebius *  (=no matching variable found or empty value)
108290001Sglebius *
109290001Sglebius ****************************************************************************
110290001Sglebius * Parameters:
111290001Sglebius *	resultbuf	char*	The resulting string without quoted
112290001Sglebius *				characters
113290001Sglebius *	datalen		size_t	The number of bytes stored in
114290001Sglebius *							resultbuf
115290001Sglebius *	varname		char*	Name of the required variable
116290001Sglebius *	varvalue	char*	Where the value of the variable should
117290001Sglebius *							be stored
118290001Sglebius *	maxlen		size_t	Max. number of bytes for varvalue
119290001Sglebius *
120290001Sglebius * Returns:
121290001Sglebius *	size_t		number of chars that have been copied to
122290001Sglebius *			varvalue
123290001Sglebius ****************************************************************************/
124290001Sglebius
125290001Sglebiussize_t
126290001Sglebiusntpq_getvar(
127290001Sglebius	const char *	resultbuf,
128290001Sglebius	size_t		datalen,
129290001Sglebius	const char *	varname,
130290001Sglebius	char *		varvalue,
131290001Sglebius	size_t		maxlen)
132290001Sglebius{
133290001Sglebius	char *	name;
134290001Sglebius	char *	value;
135293896Sglebius	size_t	idatalen;
136290001Sglebius
137290001Sglebius	value = NULL;
138290001Sglebius	idatalen = (int)datalen;
139290001Sglebius
140290001Sglebius	while (nextvar(&idatalen, &resultbuf, &name, &value)) {
141290001Sglebius		if (strcmp(varname, name) == 0) {
142290001Sglebius			ntpq_stripquotes(varvalue, value, strlen(value), maxlen);
143290001Sglebius
144290001Sglebius			return strlen(varvalue);
145290001Sglebius		}
146290001Sglebius	}
147290001Sglebius
148290001Sglebius	return 0;
149290001Sglebius}
150290001Sglebius
151290001Sglebius
152290001Sglebius/*****************************************************************************
153290001Sglebius *
154290001Sglebius *  ntpq_queryhost
155290001Sglebius *
156290001Sglebius *  Sends a mode 6 query packet to the current open host (see
157290001Sglebius *  ntpq_openhost) and stores the requested variable set in the specified
158290001Sglebius *  character buffer.
159290001Sglebius *  It returns the number of bytes read or zero for an empty result
160290001Sglebius *  (=no answer or empty value)
161290001Sglebius *
162290001Sglebius ****************************************************************************
163290001Sglebius * Parameters:
164290001Sglebius *      VARSET		u_short	Which variable set should be
165290001Sglebius *				read (PEERVARS or CLOCKVARS)
166290001Sglebius *	association	int	The association ID that should be read
167290001Sglebius *				0 represents the ntpd instance itself
168290001Sglebius *	resultbuf	char*	The resulting string without quoted
169290001Sglebius *				characters
170290001Sglebius *	maxlen		int	Max. number of bytes for varvalue
171290001Sglebius *
172290001Sglebius * Returns:
173290001Sglebius *	int		number of bytes that have been copied to
174290001Sglebius *			resultbuf
175290001Sglebius *  			- OR -
176290001Sglebius *			0 (zero) if no reply has been received or
177290001Sglebius *			another failure occured
178290001Sglebius ****************************************************************************/
179290001Sglebius
180290001Sglebiusint ntpq_queryhost(unsigned short VARSET, unsigned short association, char *resultbuf, int maxlen)
181290001Sglebius{
182290001Sglebius	const char *datap;
183290001Sglebius	int res;
184293896Sglebius	size_t	dsize;
185293896Sglebius	u_short	rstatus;
186290001Sglebius
187290001Sglebius	if ( numhosts > 0 )
188290001Sglebius		res = doquery(VARSET,association,0,0, (char *)0, &rstatus, &dsize, &datap);
189290001Sglebius	else
190290001Sglebius		return 0;
191290001Sglebius
192290001Sglebius	if ( ( res != 0) || ( dsize == 0 ) ) /* no data */
193290001Sglebius		return 0;
194290001Sglebius
195290001Sglebius	if ( dsize > maxlen)
196290001Sglebius		dsize = maxlen;
197290001Sglebius
198290001Sglebius
199290001Sglebius	/* fill result resultbuf */
200290001Sglebius	memcpy(resultbuf, datap, dsize);
201290001Sglebius
202290001Sglebius	return dsize;
203290001Sglebius}
204290001Sglebius
205290001Sglebius
206290001Sglebius
207290001Sglebius/*****************************************************************************
208290001Sglebius *
209290001Sglebius *  ntpq_openhost
210290001Sglebius *
211290001Sglebius *  Sets up a connection to the ntpd instance of a specified host. Note:
212290001Sglebius *  There is no real "connection" established because NTP solely works
213290001Sglebius *  based on UDP.
214290001Sglebius *
215290001Sglebius ****************************************************************************
216290001Sglebius * Parameters:
217290001Sglebius *	hostname	char*	Hostname/IP of the host running ntpd
218290001Sglebius *	fam		int	Address Family (AF_INET, AF_INET6, or 0)
219290001Sglebius *
220290001Sglebius * Returns:
221290001Sglebius *	int		1 if the host connection could be set up, i.e.
222290001Sglebius *			name resolution was succesful and/or IP address
223290001Sglebius *			has been validated
224290001Sglebius *  			- OR -
225290001Sglebius *			0 (zero) if a failure occured
226290001Sglebius ****************************************************************************/
227290001Sglebius
228290001Sglebiusint
229290001Sglebiusntpq_openhost(
230290001Sglebius	char *hostname,
231290001Sglebius	int fam
232290001Sglebius	)
233290001Sglebius{
234290001Sglebius	if ( openhost(hostname, fam) )
235290001Sglebius	{
236290001Sglebius		numhosts = 1;
237290001Sglebius	} else {
238290001Sglebius		numhosts = 0;
239290001Sglebius	}
240290001Sglebius
241290001Sglebius	return numhosts;
242290001Sglebius
243290001Sglebius}
244290001Sglebius
245290001Sglebius
246290001Sglebius/*****************************************************************************
247290001Sglebius *
248290001Sglebius *  ntpq_closehost
249290001Sglebius *
250290001Sglebius *  Cleans up a connection by closing the used socket. Should be called
251290001Sglebius *  when no further queries are required for the currently used host.
252290001Sglebius *
253290001Sglebius ****************************************************************************
254290001Sglebius * Parameters:
255290001Sglebius *	- none -
256290001Sglebius *
257290001Sglebius * Returns:
258290001Sglebius *	int		0 (zero) if no host has been opened before
259290001Sglebius *			- OR -
260290001Sglebius *			the resultcode from the closesocket function call
261290001Sglebius ****************************************************************************/
262290001Sglebius
263290001Sglebiusint ntpq_closehost(void)
264290001Sglebius{
265290001Sglebius	if ( numhosts )
266290001Sglebius	 return closesocket(sockfd);
267290001Sglebius
268290001Sglebius	return 0;
269290001Sglebius}
270290001Sglebius
271290001Sglebius
272290001Sglebius/*****************************************************************************
273290001Sglebius *
274290001Sglebius *  ntpq_read_associations
275290001Sglebius *
276290001Sglebius *  This function queries the ntp host for its associations and returns the
277290001Sglebius *  number of associations found.
278290001Sglebius *
279290001Sglebius *  It takes an u_short array as its first parameter, this array holds the
280290001Sglebius *  IDs of the associations,
281290001Sglebius *  the function will not write more entries than specified with the
282290001Sglebius *  max_entries parameter.
283290001Sglebius *
284290001Sglebius *  However, if more than max_entries associations were found, the return
285290001Sglebius *  value of this function will reflect the real number, even if not all
286290001Sglebius *  associations have been stored in the array.
287290001Sglebius *
288290001Sglebius ****************************************************************************
289290001Sglebius * Parameters:
290290001Sglebius *	resultbuf	u_short*Array that should hold the list of
291290001Sglebius *				association IDs
292290001Sglebius *	maxentries	int	maximum number of association IDs that can
293290001Sglebius *				be stored in resultbuf
294290001Sglebius *
295290001Sglebius * Returns:
296290001Sglebius *	int		number of association IDs stored in resultbuf
297290001Sglebius *  			- OR -
298290001Sglebius *			0 (zero) if a failure occured or no association has
299290001Sglebius *			been returned.
300290001Sglebius ****************************************************************************/
301290001Sglebius
302290001Sglebius int  ntpq_read_associations ( u_short resultbuf[], int max_entries )
303290001Sglebius{
304290001Sglebius    int i = 0;
305290001Sglebius
306290001Sglebius    if (ntpq_dogetassoc()) {
307290001Sglebius
308290001Sglebius        if(numassoc < max_entries)
309290001Sglebius          max_entries = numassoc;
310290001Sglebius
311290001Sglebius        for (i=0;i<max_entries;i++)
312290001Sglebius            resultbuf[i] = assoc_cache[i].assid;
313290001Sglebius
314290001Sglebius        return numassoc;
315290001Sglebius    }
316290001Sglebius
317290001Sglebius    return 0;
318290001Sglebius}
319290001Sglebius
320290001Sglebius
321290001Sglebius
322290001Sglebius
323290001Sglebius/*****************************************************************************
324290001Sglebius *
325290001Sglebius *  ntpq_get_assocs
326290001Sglebius *
327290001Sglebius *  This function reads the associations of a previously selected (with
328290001Sglebius *  ntpq_openhost) NTP host into its own (global) array and returns the
329290001Sglebius *  number of associations found.
330290001Sglebius *
331290001Sglebius *  The obtained association IDs can be read by using the ntpq_get_assoc_id
332290001Sglebius *  function.
333290001Sglebius *
334290001Sglebius ****************************************************************************
335290001Sglebius * Parameters:
336290001Sglebius *	- none -
337290001Sglebius *
338290001Sglebius * Returns:
339290001Sglebius *	int		number of association IDs stored in resultbuf
340290001Sglebius *  			- OR -
341290001Sglebius *			0 (zero) if a failure occured or no association has
342290001Sglebius *			been returned.
343290001Sglebius ****************************************************************************/
344290001Sglebius
345290001Sglebius int  ntpq_get_assocs ( void )
346290001Sglebius{
347290001Sglebius    return ntpq_read_associations( ntpq_associations, MAXASSOC );
348290001Sglebius}
349290001Sglebius
350290001Sglebius
351290001Sglebius/*****************************************************************************
352290001Sglebius *
353290001Sglebius *  ntpq_get_assoc_number
354290001Sglebius *
355290001Sglebius *  This function returns for a given Association ID the association number
356290001Sglebius *  in the internal association array, which is filled by the ntpq_get_assocs
357290001Sglebius *  function.
358290001Sglebius *
359290001Sglebius ****************************************************************************
360290001Sglebius * Parameters:
361290001Sglebius *	associd		int	requested associaton ID
362290001Sglebius *
363290001Sglebius * Returns:
364290001Sglebius *	int		the number of the association array element that is
365290001Sglebius *			representing the given association ID
366290001Sglebius *  			- OR -
367290001Sglebius *			-1 if a failure occured or no matching association
368290001Sglebius * 			ID has been found
369290001Sglebius ****************************************************************************/
370290001Sglebius
371290001Sglebiusint ntpq_get_assoc_number ( associd_t associd )
372290001Sglebius{
373290001Sglebius	int i;
374290001Sglebius
375290001Sglebius	for (i=0;i<numassoc;i++) {
376290001Sglebius		if (assoc_cache[i].assid == associd)
377290001Sglebius			return i;
378290001Sglebius	}
379290001Sglebius
380290001Sglebius	return -1;
381290001Sglebius
382290001Sglebius}
383290001Sglebius
384290001Sglebius
385290001Sglebius/*****************************************************************************
386290001Sglebius *
387290001Sglebius *  ntpq_read_assoc_peervars
388290001Sglebius *
389290001Sglebius *  This function reads the peervars variable-set of a specified association
390290001Sglebius *  from a NTP host and writes it to the result buffer specified, honoring
391290001Sglebius *  the maxsize limit.
392290001Sglebius *
393290001Sglebius *  It returns the number of bytes written or 0 when the variable-set is
394290001Sglebius *  empty or failed to read.
395290001Sglebius *
396290001Sglebius ****************************************************************************
397290001Sglebius * Parameters:
398290001Sglebius *	associd		int	requested associaton ID
399290001Sglebius *	resultbuf	char*	character buffer where the variable set
400290001Sglebius *				should be stored
401290001Sglebius *	maxsize		int	the maximum number of bytes that can be
402290001Sglebius *				written to resultbuf
403290001Sglebius *
404290001Sglebius * Returns:
405290001Sglebius *	int		number of chars that have been copied to
406290001Sglebius *			resultbuf
407290001Sglebius *			- OR -
408290001Sglebius *			0 (zero) if an error occured
409290001Sglebius ****************************************************************************/
410290001Sglebius
411290001Sglebiusint
412290001Sglebiusntpq_read_assoc_peervars(
413290001Sglebius	associd_t	associd,
414290001Sglebius	char *		resultbuf,
415290001Sglebius	int		maxsize
416290001Sglebius	)
417290001Sglebius{
418290001Sglebius	const char *	datap;
419290001Sglebius	int		res;
420293896Sglebius	size_t		dsize;
421290001Sglebius	u_short		rstatus;
422290001Sglebius
423290001Sglebius	res = doquery(CTL_OP_READVAR, associd, 0, 0, NULL, &rstatus,
424290001Sglebius		      &dsize, &datap);
425290001Sglebius	if (res != 0)
426290001Sglebius		return 0;
427290001Sglebius	if (dsize <= 0) {
428290001Sglebius		if (numhosts > 1)
429290001Sglebius			fprintf(stderr, "server=%s ", currenthost);
430290001Sglebius		fprintf(stderr,
431290001Sglebius			"***No information returned for association %d\n",
432290001Sglebius			associd);
433290001Sglebius
434290001Sglebius		return 0;
435290001Sglebius	}
436290001Sglebius	if (dsize > maxsize)
437290001Sglebius		dsize = maxsize;
438290001Sglebius	memcpy(resultbuf, datap, dsize);
439290001Sglebius
440290001Sglebius	return dsize;
441290001Sglebius}
442290001Sglebius
443290001Sglebius
444290001Sglebius
445290001Sglebius
446290001Sglebius/*****************************************************************************
447290001Sglebius *
448290001Sglebius *  ntpq_read_sysvars
449290001Sglebius *
450290001Sglebius *  This function reads the sysvars variable-set from a NTP host and writes it
451290001Sglebius *  to the result buffer specified, honoring the maxsize limit.
452290001Sglebius *
453290001Sglebius *  It returns the number of bytes written or 0 when the variable-set is empty
454290001Sglebius *  or could not be read.
455290001Sglebius *
456290001Sglebius ****************************************************************************
457290001Sglebius * Parameters:
458290001Sglebius *	resultbuf	char*	character buffer where the variable set
459290001Sglebius *				should be stored
460290001Sglebius *	maxsize		int	the maximum number of bytes that can be
461290001Sglebius *				written to resultbuf
462290001Sglebius *
463290001Sglebius * Returns:
464290001Sglebius *	int		number of chars that have been copied to
465290001Sglebius *			resultbuf
466290001Sglebius *			- OR -
467290001Sglebius *			0 (zero) if an error occured
468290001Sglebius ****************************************************************************/
469290001Sglebiussize_t
470290001Sglebiusntpq_read_sysvars(
471290001Sglebius	char *	resultbuf,
472290001Sglebius	size_t	maxsize
473290001Sglebius	)
474290001Sglebius{
475290001Sglebius	const char *	datap;
476290001Sglebius	int		res;
477290001Sglebius	size_t		dsize;
478290001Sglebius	u_short		rstatus;
479290001Sglebius
480290001Sglebius	res = doquery(CTL_OP_READVAR, 0, 0, 0, NULL, &rstatus,
481293896Sglebius		      &dsize, &datap);
482290001Sglebius
483290001Sglebius	if (res != 0)
484290001Sglebius		return 0;
485290001Sglebius
486293896Sglebius	if (dsize == 0) {
487290001Sglebius		if (numhosts > 1)
488290001Sglebius			fprintf(stderr, "server=%s ", currenthost);
489290001Sglebius		fprintf(stderr, "***No sysvar information returned\n");
490290001Sglebius
491290001Sglebius		return 0;
492290001Sglebius	} else {
493290001Sglebius		dsize = min(dsize, maxsize);
494290001Sglebius		memcpy(resultbuf, datap, dsize);
495290001Sglebius	}
496290001Sglebius
497290001Sglebius	return dsize;
498290001Sglebius}
499290001Sglebius
500290001Sglebius
501290001Sglebius/*****************************************************************************
502290001Sglebius *  ntpq_get_assoc_allvars
503290001Sglebius *
504290001Sglebius *  With this function all association variables for the specified association
505290001Sglebius *  ID can be requested from a NTP host. They are stored internally and can be
506290001Sglebius *  read by using the ntpq_get_peervar or ntpq_get_clockvar functions.
507290001Sglebius *
508290001Sglebius *  Basically this is only a combination of the ntpq_get_assoc_peervars and
509290001Sglebius *  ntpq_get_assoc_clockvars functions.
510290001Sglebius *
511290001Sglebius *  It returns 1 if both variable-sets (peervars and clockvars) were
512290001Sglebius *  received successfully. If one variable-set or both of them weren't
513290001Sglebius *  received,
514290001Sglebius *
515290001Sglebius ****************************************************************************
516290001Sglebius * Parameters:
517290001Sglebius *	associd		int	requested associaton ID
518290001Sglebius *
519290001Sglebius * Returns:
520290001Sglebius *	int		nonzero if at least one variable set could be read
521290001Sglebius * 			- OR -
522290001Sglebius *			0 (zero) if an error occured and both variable sets
523290001Sglebius *			could not be read
524290001Sglebius ****************************************************************************/
525290001Sglebius int  ntpq_get_assoc_allvars( associd_t associd  )
526290001Sglebius{
527290001Sglebius	return ntpq_get_assoc_peervars ( associd ) &
528290001Sglebius	       ntpq_get_assoc_clockvars( associd );
529290001Sglebius}
530290001Sglebius
531290001Sglebius
532290001Sglebius
533290001Sglebius
534290001Sglebius/*****************************************************************************
535290001Sglebius *
536290001Sglebius *  ntpq_get_sysvars
537290001Sglebius *
538290001Sglebius *  The system variables of a NTP host can be requested by using this function
539290001Sglebius *  and afterwards using ntpq_get_sysvar to read the single variable values.
540290001Sglebius *
541290001Sglebius ****************************************************************************
542290001Sglebius * Parameters:
543290001Sglebius *	- none -
544290001Sglebius *
545290001Sglebius * Returns:
546290001Sglebius *	int		nonzero if the variable set could be read
547290001Sglebius * 			- OR -
548290001Sglebius *			0 (zero) if an error occured and the sysvars
549290001Sglebius *			could not be read
550290001Sglebius ****************************************************************************/
551290001Sglebiusint
552290001Sglebiusntpq_get_sysvars(void)
553290001Sglebius{
554290001Sglebius	sysvarlen = ntpq_read_sysvars(sysvars, sizeof(sysvars));
555290001Sglebius	if (sysvarlen <= 0)
556290001Sglebius		return 0;
557290001Sglebius	else
558290001Sglebius		return 1;
559290001Sglebius}
560290001Sglebius
561290001Sglebius
562290001Sglebius/*****************************************************************************
563290001Sglebius *
564290001Sglebius *  ntp_get_peervar
565290001Sglebius *
566290001Sglebius *  This function uses the variable-set which was read by using
567290001Sglebius *  ntp_get_peervars and searches for a variable specified with varname. If
568290001Sglebius *  such a variable exists, it writes its value into
569290001Sglebius *  varvalue (maxlen specifies the size of this target buffer).
570290001Sglebius *
571290001Sglebius ****************************************************************************
572290001Sglebius * Parameters:
573290001Sglebius *	varname		char*	requested variable name
574290001Sglebius *	varvalue	char*	the buffer where the value should go into
575290001Sglebius *	maxlen		int	maximum number of bytes that can be copied to
576290001Sglebius *				varvalue
577290001Sglebius *
578290001Sglebius * Returns:
579290001Sglebius *	int		number of bytes copied to varvalue
580290001Sglebius * 			- OR -
581290001Sglebius *			0 (zero) if an error occured or the variable could
582290001Sglebius *			not be found
583290001Sglebius ****************************************************************************/
584290001Sglebiusint ntpq_get_peervar( const char *varname, char *varvalue, int maxlen)
585290001Sglebius{
586290001Sglebius    return ( ntpq_getvar(peervars,peervarlen,varname,varvalue,maxlen) );
587290001Sglebius}
588290001Sglebius
589290001Sglebius
590290001Sglebius
591290001Sglebius/*****************************************************************************
592290001Sglebius *
593290001Sglebius *  ntpq_get_assoc_peervars
594290001Sglebius *
595290001Sglebius *  This function requests the peer variables of the specified association
596290001Sglebius *  from a NTP host. In order to access the variable values, the function
597290001Sglebius *  ntpq_get_peervar must be used.
598290001Sglebius *
599290001Sglebius ****************************************************************************
600290001Sglebius * Parameters:
601290001Sglebius *	associd		int	requested associaton ID
602290001Sglebius *
603290001Sglebius * Returns:
604290001Sglebius *	int		1 (one) if the peervars have been read
605290001Sglebius * 			- OR -
606290001Sglebius *			0 (zero) if an error occured and the variable set
607290001Sglebius *			could not be read
608290001Sglebius ****************************************************************************/
609290001Sglebiusint
610290001Sglebiusntpq_get_assoc_peervars(
611290001Sglebius	associd_t associd
612290001Sglebius	)
613290001Sglebius{
614290001Sglebius	peervarlen = ntpq_read_assoc_peervars(associd, peervars,
615290001Sglebius					      sizeof(peervars));
616290001Sglebius	if (peervarlen <= 0) {
617290001Sglebius		peervar_assoc = 0;
618290001Sglebius
619290001Sglebius		return 0;
620290001Sglebius	}
621290001Sglebius	peervar_assoc = associd;
622290001Sglebius
623290001Sglebius	return 1;
624290001Sglebius}
625290001Sglebius
626290001Sglebius
627290001Sglebius/*****************************************************************************
628290001Sglebius *
629290001Sglebius *  ntp_read_assoc_clockvars
630290001Sglebius *
631290001Sglebius *  This function reads the clockvars variable-set of a specified association
632290001Sglebius *  from a NTP host and writes it to the result buffer specified, honoring
633290001Sglebius *  the maxsize limit.
634290001Sglebius *
635290001Sglebius *  It returns the number of bytes written or 0 when the variable-set is
636290001Sglebius *  empty or failed to read.
637290001Sglebius *
638290001Sglebius ****************************************************************************
639290001Sglebius * Parameters:
640290001Sglebius *	associd		int	requested associaton ID
641290001Sglebius *	resultbuf	char*	character buffer where the variable set
642290001Sglebius *				should be stored
643290001Sglebius *	maxsize		int	the maximum number of bytes that can be
644290001Sglebius *				written to resultbuf
645290001Sglebius *
646290001Sglebius * Returns:
647290001Sglebius *	int		number of chars that have been copied to
648290001Sglebius *			resultbuf
649290001Sglebius *			- OR -
650290001Sglebius *			0 (zero) if an error occured
651290001Sglebius ****************************************************************************/
652290001Sglebius
653290001Sglebiusint
654290001Sglebiusntpq_read_assoc_clockvars(
655290001Sglebius	associd_t	associd,
656290001Sglebius	char *		resultbuf,
657290001Sglebius	int		maxsize
658290001Sglebius	)
659290001Sglebius{
660290001Sglebius	const char *datap;
661290001Sglebius	int res;
662293896Sglebius	size_t dsize;
663290001Sglebius	u_short rstatus;
664290001Sglebius
665290001Sglebius	res = ntpq_doquerylist(ntpq_varlist, CTL_OP_READCLOCK, associd,
666290001Sglebius			       0, &rstatus, &dsize, &datap);
667290001Sglebius	if (res != 0)
668290001Sglebius		return 0;
669290001Sglebius
670290001Sglebius	if (dsize == 0) {
671290001Sglebius		if (numhosts > 1) /* no information returned from server */
672290001Sglebius			return 0;
673290001Sglebius	} else {
674290001Sglebius		if (dsize > maxsize)
675290001Sglebius			dsize = maxsize;
676290001Sglebius		memcpy(resultbuf, datap, dsize);
677290001Sglebius	}
678290001Sglebius
679290001Sglebius	return dsize;
680290001Sglebius}
681290001Sglebius
682290001Sglebius
683290001Sglebius
684290001Sglebius/*****************************************************************************
685290001Sglebius *
686290001Sglebius *  ntpq_get_assoc_clocktype
687290001Sglebius *
688290001Sglebius *  This function returns a clocktype value for a given association number
689290001Sglebius *  (not ID!):
690290001Sglebius *
691290001Sglebius *  NTP_CLOCKTYPE_UNKNOWN   Unknown clock type
692290001Sglebius *  NTP_CLOCKTYPE_BROADCAST Broadcast server
693290001Sglebius *  NTP_CLOCKTYPE_LOCAL     Local clock
694290001Sglebius *  NTP_CLOCKTYPE_UNICAST   Unicast server
695290001Sglebius *  NTP_CLOCKTYPE_MULTICAST Multicast server
696290001Sglebius *
697290001Sglebius ****************************************************************************/
698290001Sglebiusint
699290001Sglebiusntpq_get_assoc_clocktype(
700290001Sglebius	int assoc_index
701290001Sglebius	)
702290001Sglebius{
703290001Sglebius	associd_t	associd;
704290001Sglebius	int		i;
705290001Sglebius	int		rc;
706290001Sglebius	sockaddr_u	dum_store;
707290001Sglebius	char		dstadr[LENHOSTNAME];
708290001Sglebius	char		resultbuf[NTPQ_BUFLEN];
709290001Sglebius
710290001Sglebius	if (assoc_index < 0 || assoc_index >= numassoc)
711290001Sglebius		return -1;
712290001Sglebius
713290001Sglebius	associd = assoc_cache[assoc_index].assid;
714290001Sglebius	if (associd == peervar_assoc) {
715290001Sglebius		rc = ntpq_get_peervar("dstadr", dstadr, sizeof(dstadr));
716290001Sglebius	} else {
717290001Sglebius		i = ntpq_read_assoc_peervars(associd, resultbuf,
718290001Sglebius					     sizeof(resultbuf));
719290001Sglebius		if (i <= 0)
720290001Sglebius			return -1;
721290001Sglebius		rc = ntpq_getvar(resultbuf, i, "dstadr", dstadr,
722290001Sglebius				 sizeof(dstadr));
723290001Sglebius	}
724290001Sglebius
725290001Sglebius	if (0 != rc && decodenetnum(dstadr, &dum_store))
726290001Sglebius		return ntpq_decodeaddrtype(&dum_store);
727290001Sglebius
728290001Sglebius	return -1;
729290001Sglebius}
730290001Sglebius
731290001Sglebius
732290001Sglebius
733290001Sglebius/*****************************************************************************
734290001Sglebius *
735290001Sglebius *  ntpq_get_assoc_clockvars
736290001Sglebius *
737290001Sglebius *  With this function the clock variables of the specified association are
738290001Sglebius *  requested from a NTP host. This makes only sense for associations with
739290001Sglebius *  the type 'l' (Local Clock) and you should check this with
740290001Sglebius *  ntpq_get_assoc_clocktype for each association, before you use this function
741290001Sglebius *  on it.
742290001Sglebius *
743290001Sglebius ****************************************************************************
744290001Sglebius * Parameters:
745290001Sglebius *	associd		int	requested associaton ID
746290001Sglebius *
747290001Sglebius * Returns:
748290001Sglebius *	int		1 (one) if the clockvars have been read
749290001Sglebius * 			- OR -
750290001Sglebius *			0 (zero) if an error occured and the variable set
751290001Sglebius *			could not be read
752290001Sglebius ****************************************************************************/
753290001Sglebiusint  ntpq_get_assoc_clockvars( associd_t associd )
754290001Sglebius{
755290001Sglebius	if (NTP_CLOCKTYPE_LOCAL != ntpq_get_assoc_clocktype(
756290001Sglebius	    ntpq_get_assoc_number(associd)))
757290001Sglebius		return 0;
758290001Sglebius	clockvarlen = ntpq_read_assoc_clockvars( associd, clockvars,
759290001Sglebius						 sizeof(clockvars) );
760290001Sglebius	if ( clockvarlen <= 0 ) {
761290001Sglebius		clockvar_assoc = 0;
762290001Sglebius		return 0;
763290001Sglebius	} else {
764290001Sglebius		clockvar_assoc = associd;
765290001Sglebius		return 1;
766290001Sglebius	}
767290001Sglebius}
768290001Sglebius
769290001Sglebius
770