1258945Sroberto/*****************************************************************************
2258945Sroberto *
3258945Sroberto *  libntpq.c
4258945Sroberto *
5258945Sroberto *  This is the wrapper library for ntpq, the NTP query utility.
6258945Sroberto *  This library reuses the sourcecode from ntpq and exports a number
7258945Sroberto *  of useful functions in a library that can be linked against applications
8258945Sroberto *  that need to query the status of a running ntpd. The whole
9258945Sroberto *  communcation is based on mode 6 packets.
10258945Sroberto *
11258945Sroberto ****************************************************************************/
12258945Sroberto#define LIBNTPQ_C
13258945Sroberto#define NO_MAIN_ALLOWED 1
14258945Sroberto/* #define BUILD_AS_LIB		Already provided by the Makefile */
15258945Sroberto
16258945Sroberto#include "ntpq.c"
17258945Sroberto#include "libntpq.h"
18258945Sroberto
19258945Sroberto/* Function Prototypes */
20258945Sroberto
21258945Sroberto
22258945Srobertoconst char *Version = "libntpq 0.3beta";
23258945Sroberto
24258945Sroberto/* global variables used for holding snapshots of data */
25258945Srobertochar peervars[NTPQ_BUFLEN];
26258945Srobertoint peervarlen = 0;
27258945Srobertoassocid_t peervar_assoc = 0;
28258945Srobertochar clockvars[NTPQ_BUFLEN];
29258945Srobertoint clockvarlen = 0;
30258945Srobertoint clockvar_assoc = 0;
31258945Srobertochar sysvars[NTPQ_BUFLEN];
32258945Srobertoint sysvarlen = 0;
33258945Srobertochar *ntpq_resultbuffer[NTPQ_BUFLEN];
34258945Srobertounsigned short ntpq_associations[MAXASSOC];
35258945Srobertostruct ntpq_varlist ntpq_varlist[MAXLIST];
36258945Sroberto
37258945Sroberto/*****************************************************************************
38258945Sroberto *
39258945Sroberto *  ntpq_stripquotes
40258945Sroberto *
41258945Sroberto *  Parses a given character buffer srcbuf and removes all quoted
42258945Sroberto *  characters. The resulting string is copied to the specified
43258945Sroberto *  resultbuf character buffer.  E.g. \" will be translated into "
44258945Sroberto *
45258945Sroberto ****************************************************************************
46258945Sroberto * Parameters:
47258945Sroberto *	resultbuf	char*	The resulting string without quoted
48258945Sroberto *				characters
49258945Sroberto *	srcbuf		char*	The buffer holding the original string
50258945Sroberto *	datalen		int	The number of bytes stored in srcbuf
51258945Sroberto *	maxlen		int	Max. number of bytes for resultbuf
52258945Sroberto *
53258945Sroberto * Returns:
54258945Sroberto *	int		number of chars that have been copied to
55258945Sroberto *			resultbuf
56258945Sroberto ****************************************************************************/
57258945Sroberto
58258945Srobertoint ntpq_stripquotes ( char *resultbuf, char *srcbuf, int datalen, int maxlen )
59258945Sroberto{
60258945Sroberto	char* tmpbuf = srcbuf;
61258945Sroberto
62258945Sroberto	while ( *tmpbuf != 0 )
63258945Sroberto	{
64258945Sroberto		if ( *tmpbuf == '\"' )
65258945Sroberto		{
66258945Sroberto			tmpbuf++;
67258945Sroberto			continue;
68258945Sroberto		}
69258945Sroberto
70258945Sroberto		if ( *tmpbuf == '\\' )
71258945Sroberto		{
72258945Sroberto			tmpbuf++;
73258945Sroberto			switch ( *tmpbuf )
74258945Sroberto			{
75258945Sroberto				/* ignore if end of string */
76258945Sroberto				case 0:
77258945Sroberto					continue;
78258945Sroberto				/* skip and do not copy */
79258945Sroberto				case '\"': /* quotes */
80258945Sroberto				case 'n': /*newline*/
81258945Sroberto				case 'r': /*carriage return*/
82258945Sroberto				case 'g': /*bell*/
83258945Sroberto				case 't': /*tab*/
84258945Sroberto					tmpbuf++;
85258945Sroberto					continue;
86258945Sroberto			}
87258945Sroberto		}
88258945Sroberto
89258945Sroberto		*resultbuf++ = *tmpbuf++;
90258945Sroberto
91258945Sroberto	}
92258945Sroberto
93258945Sroberto	*resultbuf = 0;
94258945Sroberto	return strlen(resultbuf);
95258945Sroberto}
96258945Sroberto
97258945Sroberto
98258945Sroberto/*****************************************************************************
99258945Sroberto *
100258945Sroberto *  ntpq_getvar
101258945Sroberto *
102258945Sroberto *  This function parses a given buffer for a variable/value pair and
103258945Sroberto *  copies the value of the requested variable into the specified
104258945Sroberto *  varvalue buffer.
105258945Sroberto *
106258945Sroberto *  It returns the number of bytes copied or zero for an empty result
107258945Sroberto *  (=no matching variable found or empty value)
108258945Sroberto *
109258945Sroberto ****************************************************************************
110258945Sroberto * Parameters:
111258945Sroberto *	resultbuf	char*	The resulting string without quoted
112258945Sroberto *				characters
113258945Sroberto *	datalen		size_t	The number of bytes stored in
114258945Sroberto *							resultbuf
115258945Sroberto *	varname		char*	Name of the required variable
116258945Sroberto *	varvalue	char*	Where the value of the variable should
117258945Sroberto *							be stored
118258945Sroberto *	maxlen		size_t	Max. number of bytes for varvalue
119258945Sroberto *
120258945Sroberto * Returns:
121258945Sroberto *	size_t		number of chars that have been copied to
122258945Sroberto *			varvalue
123258945Sroberto ****************************************************************************/
124258945Sroberto
125258945Srobertosize_t
126258945Srobertontpq_getvar(
127258945Sroberto	const char *	resultbuf,
128258945Sroberto	size_t		datalen,
129258945Sroberto	const char *	varname,
130258945Sroberto	char *		varvalue,
131258945Sroberto	size_t		maxlen)
132258945Sroberto{
133258945Sroberto	char *	name;
134258945Sroberto	char *	value;
135293894Sglebius	size_t	idatalen;
136258945Sroberto
137258945Sroberto	value = NULL;
138258945Sroberto	idatalen = (int)datalen;
139258945Sroberto
140258945Sroberto	while (nextvar(&idatalen, &resultbuf, &name, &value)) {
141258945Sroberto		if (strcmp(varname, name) == 0) {
142258945Sroberto			ntpq_stripquotes(varvalue, value, strlen(value), maxlen);
143258945Sroberto
144258945Sroberto			return strlen(varvalue);
145258945Sroberto		}
146258945Sroberto	}
147258945Sroberto
148258945Sroberto	return 0;
149258945Sroberto}
150258945Sroberto
151258945Sroberto
152258945Sroberto/*****************************************************************************
153258945Sroberto *
154258945Sroberto *  ntpq_queryhost
155258945Sroberto *
156258945Sroberto *  Sends a mode 6 query packet to the current open host (see
157258945Sroberto *  ntpq_openhost) and stores the requested variable set in the specified
158258945Sroberto *  character buffer.
159258945Sroberto *  It returns the number of bytes read or zero for an empty result
160258945Sroberto *  (=no answer or empty value)
161258945Sroberto *
162258945Sroberto ****************************************************************************
163258945Sroberto * Parameters:
164258945Sroberto *      VARSET		u_short	Which variable set should be
165258945Sroberto *				read (PEERVARS or CLOCKVARS)
166258945Sroberto *	association	int	The association ID that should be read
167258945Sroberto *				0 represents the ntpd instance itself
168258945Sroberto *	resultbuf	char*	The resulting string without quoted
169258945Sroberto *				characters
170258945Sroberto *	maxlen		int	Max. number of bytes for varvalue
171258945Sroberto *
172258945Sroberto * Returns:
173258945Sroberto *	int		number of bytes that have been copied to
174258945Sroberto *			resultbuf
175258945Sroberto *  			- OR -
176258945Sroberto *			0 (zero) if no reply has been received or
177258945Sroberto *			another failure occured
178258945Sroberto ****************************************************************************/
179258945Sroberto
180258945Srobertoint ntpq_queryhost(unsigned short VARSET, unsigned short association, char *resultbuf, int maxlen)
181258945Sroberto{
182258945Sroberto	const char *datap;
183258945Sroberto	int res;
184293894Sglebius	size_t	dsize;
185293894Sglebius	u_short	rstatus;
186258945Sroberto
187258945Sroberto	if ( numhosts > 0 )
188258945Sroberto		res = doquery(VARSET,association,0,0, (char *)0, &rstatus, &dsize, &datap);
189258945Sroberto	else
190258945Sroberto		return 0;
191258945Sroberto
192258945Sroberto	if ( ( res != 0) || ( dsize == 0 ) ) /* no data */
193258945Sroberto		return 0;
194258945Sroberto
195258945Sroberto	if ( dsize > maxlen)
196258945Sroberto		dsize = maxlen;
197258945Sroberto
198258945Sroberto
199258945Sroberto	/* fill result resultbuf */
200258945Sroberto	memcpy(resultbuf, datap, dsize);
201258945Sroberto
202258945Sroberto	return dsize;
203258945Sroberto}
204258945Sroberto
205258945Sroberto
206258945Sroberto
207258945Sroberto/*****************************************************************************
208258945Sroberto *
209258945Sroberto *  ntpq_openhost
210258945Sroberto *
211258945Sroberto *  Sets up a connection to the ntpd instance of a specified host. Note:
212258945Sroberto *  There is no real "connection" established because NTP solely works
213258945Sroberto *  based on UDP.
214258945Sroberto *
215258945Sroberto ****************************************************************************
216258945Sroberto * Parameters:
217258945Sroberto *	hostname	char*	Hostname/IP of the host running ntpd
218280849Scy *	fam		int	Address Family (AF_INET, AF_INET6, or 0)
219258945Sroberto *
220258945Sroberto * Returns:
221258945Sroberto *	int		1 if the host connection could be set up, i.e.
222258945Sroberto *			name resolution was succesful and/or IP address
223258945Sroberto *			has been validated
224258945Sroberto *  			- OR -
225258945Sroberto *			0 (zero) if a failure occured
226258945Sroberto ****************************************************************************/
227258945Sroberto
228280849Scyint
229280849Scyntpq_openhost(
230280849Scy	char *hostname,
231280849Scy	int fam
232280849Scy	)
233258945Sroberto{
234280849Scy	if ( openhost(hostname, fam) )
235258945Sroberto	{
236258945Sroberto		numhosts = 1;
237258945Sroberto	} else {
238258945Sroberto		numhosts = 0;
239258945Sroberto	}
240258945Sroberto
241258945Sroberto	return numhosts;
242258945Sroberto
243258945Sroberto}
244258945Sroberto
245258945Sroberto
246258945Sroberto/*****************************************************************************
247258945Sroberto *
248258945Sroberto *  ntpq_closehost
249258945Sroberto *
250258945Sroberto *  Cleans up a connection by closing the used socket. Should be called
251258945Sroberto *  when no further queries are required for the currently used host.
252258945Sroberto *
253258945Sroberto ****************************************************************************
254258945Sroberto * Parameters:
255258945Sroberto *	- none -
256258945Sroberto *
257258945Sroberto * Returns:
258258945Sroberto *	int		0 (zero) if no host has been opened before
259258945Sroberto *			- OR -
260258945Sroberto *			the resultcode from the closesocket function call
261258945Sroberto ****************************************************************************/
262258945Sroberto
263258945Srobertoint ntpq_closehost(void)
264258945Sroberto{
265258945Sroberto	if ( numhosts )
266258945Sroberto	 return closesocket(sockfd);
267258945Sroberto
268258945Sroberto	return 0;
269258945Sroberto}
270258945Sroberto
271258945Sroberto
272258945Sroberto/*****************************************************************************
273258945Sroberto *
274258945Sroberto *  ntpq_read_associations
275258945Sroberto *
276258945Sroberto *  This function queries the ntp host for its associations and returns the
277258945Sroberto *  number of associations found.
278258945Sroberto *
279258945Sroberto *  It takes an u_short array as its first parameter, this array holds the
280258945Sroberto *  IDs of the associations,
281258945Sroberto *  the function will not write more entries than specified with the
282258945Sroberto *  max_entries parameter.
283258945Sroberto *
284258945Sroberto *  However, if more than max_entries associations were found, the return
285258945Sroberto *  value of this function will reflect the real number, even if not all
286258945Sroberto *  associations have been stored in the array.
287258945Sroberto *
288258945Sroberto ****************************************************************************
289258945Sroberto * Parameters:
290258945Sroberto *	resultbuf	u_short*Array that should hold the list of
291258945Sroberto *				association IDs
292258945Sroberto *	maxentries	int	maximum number of association IDs that can
293258945Sroberto *				be stored in resultbuf
294258945Sroberto *
295258945Sroberto * Returns:
296258945Sroberto *	int		number of association IDs stored in resultbuf
297258945Sroberto *  			- OR -
298258945Sroberto *			0 (zero) if a failure occured or no association has
299258945Sroberto *			been returned.
300258945Sroberto ****************************************************************************/
301258945Sroberto
302258945Sroberto int  ntpq_read_associations ( u_short resultbuf[], int max_entries )
303258945Sroberto{
304258945Sroberto    int i = 0;
305258945Sroberto
306258945Sroberto    if (ntpq_dogetassoc()) {
307258945Sroberto
308258945Sroberto        if(numassoc < max_entries)
309258945Sroberto          max_entries = numassoc;
310258945Sroberto
311258945Sroberto        for (i=0;i<max_entries;i++)
312258945Sroberto            resultbuf[i] = assoc_cache[i].assid;
313258945Sroberto
314258945Sroberto        return numassoc;
315258945Sroberto    }
316258945Sroberto
317258945Sroberto    return 0;
318258945Sroberto}
319258945Sroberto
320258945Sroberto
321258945Sroberto
322258945Sroberto
323258945Sroberto/*****************************************************************************
324258945Sroberto *
325258945Sroberto *  ntpq_get_assocs
326258945Sroberto *
327258945Sroberto *  This function reads the associations of a previously selected (with
328258945Sroberto *  ntpq_openhost) NTP host into its own (global) array and returns the
329258945Sroberto *  number of associations found.
330258945Sroberto *
331258945Sroberto *  The obtained association IDs can be read by using the ntpq_get_assoc_id
332258945Sroberto *  function.
333258945Sroberto *
334258945Sroberto ****************************************************************************
335258945Sroberto * Parameters:
336258945Sroberto *	- none -
337258945Sroberto *
338258945Sroberto * Returns:
339258945Sroberto *	int		number of association IDs stored in resultbuf
340258945Sroberto *  			- OR -
341258945Sroberto *			0 (zero) if a failure occured or no association has
342258945Sroberto *			been returned.
343258945Sroberto ****************************************************************************/
344258945Sroberto
345258945Sroberto int  ntpq_get_assocs ( void )
346258945Sroberto{
347258945Sroberto    return ntpq_read_associations( ntpq_associations, MAXASSOC );
348258945Sroberto}
349258945Sroberto
350258945Sroberto
351258945Sroberto/*****************************************************************************
352258945Sroberto *
353258945Sroberto *  ntpq_get_assoc_number
354258945Sroberto *
355258945Sroberto *  This function returns for a given Association ID the association number
356258945Sroberto *  in the internal association array, which is filled by the ntpq_get_assocs
357258945Sroberto *  function.
358258945Sroberto *
359258945Sroberto ****************************************************************************
360258945Sroberto * Parameters:
361258945Sroberto *	associd		int	requested associaton ID
362258945Sroberto *
363258945Sroberto * Returns:
364258945Sroberto *	int		the number of the association array element that is
365258945Sroberto *			representing the given association ID
366258945Sroberto *  			- OR -
367258945Sroberto *			-1 if a failure occured or no matching association
368258945Sroberto * 			ID has been found
369258945Sroberto ****************************************************************************/
370258945Sroberto
371258945Srobertoint ntpq_get_assoc_number ( associd_t associd )
372258945Sroberto{
373258945Sroberto	int i;
374258945Sroberto
375258945Sroberto	for (i=0;i<numassoc;i++) {
376258945Sroberto		if (assoc_cache[i].assid == associd)
377258945Sroberto			return i;
378258945Sroberto	}
379258945Sroberto
380258945Sroberto	return -1;
381258945Sroberto
382258945Sroberto}
383258945Sroberto
384258945Sroberto
385258945Sroberto/*****************************************************************************
386258945Sroberto *
387258945Sroberto *  ntpq_read_assoc_peervars
388258945Sroberto *
389258945Sroberto *  This function reads the peervars variable-set of a specified association
390258945Sroberto *  from a NTP host and writes it to the result buffer specified, honoring
391258945Sroberto *  the maxsize limit.
392258945Sroberto *
393258945Sroberto *  It returns the number of bytes written or 0 when the variable-set is
394258945Sroberto *  empty or failed to read.
395258945Sroberto *
396258945Sroberto ****************************************************************************
397258945Sroberto * Parameters:
398258945Sroberto *	associd		int	requested associaton ID
399258945Sroberto *	resultbuf	char*	character buffer where the variable set
400258945Sroberto *				should be stored
401258945Sroberto *	maxsize		int	the maximum number of bytes that can be
402258945Sroberto *				written to resultbuf
403258945Sroberto *
404258945Sroberto * Returns:
405258945Sroberto *	int		number of chars that have been copied to
406258945Sroberto *			resultbuf
407258945Sroberto *			- OR -
408258945Sroberto *			0 (zero) if an error occured
409258945Sroberto ****************************************************************************/
410258945Sroberto
411258945Srobertoint
412258945Srobertontpq_read_assoc_peervars(
413258945Sroberto	associd_t	associd,
414258945Sroberto	char *		resultbuf,
415258945Sroberto	int		maxsize
416258945Sroberto	)
417258945Sroberto{
418258945Sroberto	const char *	datap;
419258945Sroberto	int		res;
420293894Sglebius	size_t		dsize;
421258945Sroberto	u_short		rstatus;
422258945Sroberto
423258945Sroberto	res = doquery(CTL_OP_READVAR, associd, 0, 0, NULL, &rstatus,
424258945Sroberto		      &dsize, &datap);
425258945Sroberto	if (res != 0)
426258945Sroberto		return 0;
427258945Sroberto	if (dsize <= 0) {
428258945Sroberto		if (numhosts > 1)
429258945Sroberto			fprintf(stderr, "server=%s ", currenthost);
430258945Sroberto		fprintf(stderr,
431258945Sroberto			"***No information returned for association %d\n",
432258945Sroberto			associd);
433258945Sroberto
434258945Sroberto		return 0;
435258945Sroberto	}
436258945Sroberto	if (dsize > maxsize)
437258945Sroberto		dsize = maxsize;
438258945Sroberto	memcpy(resultbuf, datap, dsize);
439258945Sroberto
440258945Sroberto	return dsize;
441258945Sroberto}
442258945Sroberto
443258945Sroberto
444258945Sroberto
445258945Sroberto
446258945Sroberto/*****************************************************************************
447258945Sroberto *
448258945Sroberto *  ntpq_read_sysvars
449258945Sroberto *
450258945Sroberto *  This function reads the sysvars variable-set from a NTP host and writes it
451258945Sroberto *  to the result buffer specified, honoring the maxsize limit.
452258945Sroberto *
453258945Sroberto *  It returns the number of bytes written or 0 when the variable-set is empty
454258945Sroberto *  or could not be read.
455258945Sroberto *
456258945Sroberto ****************************************************************************
457258945Sroberto * Parameters:
458258945Sroberto *	resultbuf	char*	character buffer where the variable set
459258945Sroberto *				should be stored
460258945Sroberto *	maxsize		int	the maximum number of bytes that can be
461258945Sroberto *				written to resultbuf
462258945Sroberto *
463258945Sroberto * Returns:
464258945Sroberto *	int		number of chars that have been copied to
465258945Sroberto *			resultbuf
466258945Sroberto *			- OR -
467258945Sroberto *			0 (zero) if an error occured
468258945Sroberto ****************************************************************************/
469258945Srobertosize_t
470258945Srobertontpq_read_sysvars(
471258945Sroberto	char *	resultbuf,
472258945Sroberto	size_t	maxsize
473258945Sroberto	)
474258945Sroberto{
475258945Sroberto	const char *	datap;
476258945Sroberto	int		res;
477258945Sroberto	size_t		dsize;
478258945Sroberto	u_short		rstatus;
479258945Sroberto
480258945Sroberto	res = doquery(CTL_OP_READVAR, 0, 0, 0, NULL, &rstatus,
481293894Sglebius		      &dsize, &datap);
482258945Sroberto
483258945Sroberto	if (res != 0)
484258945Sroberto		return 0;
485258945Sroberto
486293894Sglebius	if (dsize == 0) {
487258945Sroberto		if (numhosts > 1)
488258945Sroberto			fprintf(stderr, "server=%s ", currenthost);
489258945Sroberto		fprintf(stderr, "***No sysvar information returned\n");
490258945Sroberto
491258945Sroberto		return 0;
492258945Sroberto	} else {
493258945Sroberto		dsize = min(dsize, maxsize);
494258945Sroberto		memcpy(resultbuf, datap, dsize);
495258945Sroberto	}
496258945Sroberto
497258945Sroberto	return dsize;
498258945Sroberto}
499258945Sroberto
500258945Sroberto
501258945Sroberto/*****************************************************************************
502258945Sroberto *  ntpq_get_assoc_allvars
503258945Sroberto *
504258945Sroberto *  With this function all association variables for the specified association
505258945Sroberto *  ID can be requested from a NTP host. They are stored internally and can be
506258945Sroberto *  read by using the ntpq_get_peervar or ntpq_get_clockvar functions.
507258945Sroberto *
508258945Sroberto *  Basically this is only a combination of the ntpq_get_assoc_peervars and
509258945Sroberto *  ntpq_get_assoc_clockvars functions.
510258945Sroberto *
511258945Sroberto *  It returns 1 if both variable-sets (peervars and clockvars) were
512258945Sroberto *  received successfully. If one variable-set or both of them weren't
513258945Sroberto *  received,
514258945Sroberto *
515258945Sroberto ****************************************************************************
516258945Sroberto * Parameters:
517258945Sroberto *	associd		int	requested associaton ID
518258945Sroberto *
519258945Sroberto * Returns:
520258945Sroberto *	int		nonzero if at least one variable set could be read
521258945Sroberto * 			- OR -
522258945Sroberto *			0 (zero) if an error occured and both variable sets
523258945Sroberto *			could not be read
524258945Sroberto ****************************************************************************/
525258945Sroberto int  ntpq_get_assoc_allvars( associd_t associd  )
526258945Sroberto{
527258945Sroberto	return ntpq_get_assoc_peervars ( associd ) &
528258945Sroberto	       ntpq_get_assoc_clockvars( associd );
529258945Sroberto}
530258945Sroberto
531258945Sroberto
532258945Sroberto
533258945Sroberto
534258945Sroberto/*****************************************************************************
535258945Sroberto *
536258945Sroberto *  ntpq_get_sysvars
537258945Sroberto *
538258945Sroberto *  The system variables of a NTP host can be requested by using this function
539258945Sroberto *  and afterwards using ntpq_get_sysvar to read the single variable values.
540258945Sroberto *
541258945Sroberto ****************************************************************************
542258945Sroberto * Parameters:
543258945Sroberto *	- none -
544258945Sroberto *
545258945Sroberto * Returns:
546258945Sroberto *	int		nonzero if the variable set could be read
547258945Sroberto * 			- OR -
548258945Sroberto *			0 (zero) if an error occured and the sysvars
549258945Sroberto *			could not be read
550258945Sroberto ****************************************************************************/
551258945Srobertoint
552258945Srobertontpq_get_sysvars(void)
553258945Sroberto{
554258945Sroberto	sysvarlen = ntpq_read_sysvars(sysvars, sizeof(sysvars));
555258945Sroberto	if (sysvarlen <= 0)
556258945Sroberto		return 0;
557258945Sroberto	else
558258945Sroberto		return 1;
559258945Sroberto}
560258945Sroberto
561258945Sroberto
562258945Sroberto/*****************************************************************************
563258945Sroberto *
564258945Sroberto *  ntp_get_peervar
565258945Sroberto *
566258945Sroberto *  This function uses the variable-set which was read by using
567258945Sroberto *  ntp_get_peervars and searches for a variable specified with varname. If
568258945Sroberto *  such a variable exists, it writes its value into
569258945Sroberto *  varvalue (maxlen specifies the size of this target buffer).
570258945Sroberto *
571258945Sroberto ****************************************************************************
572258945Sroberto * Parameters:
573258945Sroberto *	varname		char*	requested variable name
574258945Sroberto *	varvalue	char*	the buffer where the value should go into
575258945Sroberto *	maxlen		int	maximum number of bytes that can be copied to
576258945Sroberto *				varvalue
577258945Sroberto *
578258945Sroberto * Returns:
579258945Sroberto *	int		number of bytes copied to varvalue
580258945Sroberto * 			- OR -
581258945Sroberto *			0 (zero) if an error occured or the variable could
582258945Sroberto *			not be found
583258945Sroberto ****************************************************************************/
584258945Srobertoint ntpq_get_peervar( const char *varname, char *varvalue, int maxlen)
585258945Sroberto{
586258945Sroberto    return ( ntpq_getvar(peervars,peervarlen,varname,varvalue,maxlen) );
587258945Sroberto}
588258945Sroberto
589258945Sroberto
590258945Sroberto
591258945Sroberto/*****************************************************************************
592258945Sroberto *
593258945Sroberto *  ntpq_get_assoc_peervars
594258945Sroberto *
595258945Sroberto *  This function requests the peer variables of the specified association
596258945Sroberto *  from a NTP host. In order to access the variable values, the function
597258945Sroberto *  ntpq_get_peervar must be used.
598258945Sroberto *
599258945Sroberto ****************************************************************************
600258945Sroberto * Parameters:
601258945Sroberto *	associd		int	requested associaton ID
602258945Sroberto *
603258945Sroberto * Returns:
604258945Sroberto *	int		1 (one) if the peervars have been read
605258945Sroberto * 			- OR -
606258945Sroberto *			0 (zero) if an error occured and the variable set
607258945Sroberto *			could not be read
608258945Sroberto ****************************************************************************/
609258945Srobertoint
610258945Srobertontpq_get_assoc_peervars(
611258945Sroberto	associd_t associd
612258945Sroberto	)
613258945Sroberto{
614258945Sroberto	peervarlen = ntpq_read_assoc_peervars(associd, peervars,
615258945Sroberto					      sizeof(peervars));
616258945Sroberto	if (peervarlen <= 0) {
617258945Sroberto		peervar_assoc = 0;
618258945Sroberto
619258945Sroberto		return 0;
620258945Sroberto	}
621258945Sroberto	peervar_assoc = associd;
622258945Sroberto
623258945Sroberto	return 1;
624258945Sroberto}
625258945Sroberto
626258945Sroberto
627258945Sroberto/*****************************************************************************
628258945Sroberto *
629258945Sroberto *  ntp_read_assoc_clockvars
630258945Sroberto *
631258945Sroberto *  This function reads the clockvars variable-set of a specified association
632258945Sroberto *  from a NTP host and writes it to the result buffer specified, honoring
633258945Sroberto *  the maxsize limit.
634258945Sroberto *
635258945Sroberto *  It returns the number of bytes written or 0 when the variable-set is
636258945Sroberto *  empty or failed to read.
637258945Sroberto *
638258945Sroberto ****************************************************************************
639258945Sroberto * Parameters:
640258945Sroberto *	associd		int	requested associaton ID
641258945Sroberto *	resultbuf	char*	character buffer where the variable set
642258945Sroberto *				should be stored
643258945Sroberto *	maxsize		int	the maximum number of bytes that can be
644258945Sroberto *				written to resultbuf
645258945Sroberto *
646258945Sroberto * Returns:
647258945Sroberto *	int		number of chars that have been copied to
648258945Sroberto *			resultbuf
649258945Sroberto *			- OR -
650258945Sroberto *			0 (zero) if an error occured
651258945Sroberto ****************************************************************************/
652258945Sroberto
653258945Srobertoint
654258945Srobertontpq_read_assoc_clockvars(
655258945Sroberto	associd_t	associd,
656258945Sroberto	char *		resultbuf,
657258945Sroberto	int		maxsize
658258945Sroberto	)
659258945Sroberto{
660258945Sroberto	const char *datap;
661258945Sroberto	int res;
662293894Sglebius	size_t dsize;
663258945Sroberto	u_short rstatus;
664258945Sroberto
665258945Sroberto	res = ntpq_doquerylist(ntpq_varlist, CTL_OP_READCLOCK, associd,
666258945Sroberto			       0, &rstatus, &dsize, &datap);
667258945Sroberto	if (res != 0)
668258945Sroberto		return 0;
669258945Sroberto
670258945Sroberto	if (dsize == 0) {
671258945Sroberto		if (numhosts > 1) /* no information returned from server */
672258945Sroberto			return 0;
673258945Sroberto	} else {
674258945Sroberto		if (dsize > maxsize)
675258945Sroberto			dsize = maxsize;
676258945Sroberto		memcpy(resultbuf, datap, dsize);
677258945Sroberto	}
678258945Sroberto
679258945Sroberto	return dsize;
680258945Sroberto}
681258945Sroberto
682258945Sroberto
683258945Sroberto
684258945Sroberto/*****************************************************************************
685258945Sroberto *
686258945Sroberto *  ntpq_get_assoc_clocktype
687258945Sroberto *
688258945Sroberto *  This function returns a clocktype value for a given association number
689258945Sroberto *  (not ID!):
690258945Sroberto *
691258945Sroberto *  NTP_CLOCKTYPE_UNKNOWN   Unknown clock type
692258945Sroberto *  NTP_CLOCKTYPE_BROADCAST Broadcast server
693258945Sroberto *  NTP_CLOCKTYPE_LOCAL     Local clock
694258945Sroberto *  NTP_CLOCKTYPE_UNICAST   Unicast server
695258945Sroberto *  NTP_CLOCKTYPE_MULTICAST Multicast server
696258945Sroberto *
697258945Sroberto ****************************************************************************/
698258945Srobertoint
699258945Srobertontpq_get_assoc_clocktype(
700258945Sroberto	int assoc_index
701258945Sroberto	)
702258945Sroberto{
703258945Sroberto	associd_t	associd;
704258945Sroberto	int		i;
705258945Sroberto	int		rc;
706258945Sroberto	sockaddr_u	dum_store;
707258945Sroberto	char		dstadr[LENHOSTNAME];
708258945Sroberto	char		resultbuf[NTPQ_BUFLEN];
709258945Sroberto
710258945Sroberto	if (assoc_index < 0 || assoc_index >= numassoc)
711258945Sroberto		return -1;
712258945Sroberto
713258945Sroberto	associd = assoc_cache[assoc_index].assid;
714258945Sroberto	if (associd == peervar_assoc) {
715258945Sroberto		rc = ntpq_get_peervar("dstadr", dstadr, sizeof(dstadr));
716258945Sroberto	} else {
717258945Sroberto		i = ntpq_read_assoc_peervars(associd, resultbuf,
718258945Sroberto					     sizeof(resultbuf));
719258945Sroberto		if (i <= 0)
720258945Sroberto			return -1;
721258945Sroberto		rc = ntpq_getvar(resultbuf, i, "dstadr", dstadr,
722258945Sroberto				 sizeof(dstadr));
723258945Sroberto	}
724258945Sroberto
725258945Sroberto	if (0 != rc && decodenetnum(dstadr, &dum_store))
726258945Sroberto		return ntpq_decodeaddrtype(&dum_store);
727258945Sroberto
728258945Sroberto	return -1;
729258945Sroberto}
730258945Sroberto
731258945Sroberto
732258945Sroberto
733258945Sroberto/*****************************************************************************
734258945Sroberto *
735258945Sroberto *  ntpq_get_assoc_clockvars
736258945Sroberto *
737258945Sroberto *  With this function the clock variables of the specified association are
738258945Sroberto *  requested from a NTP host. This makes only sense for associations with
739258945Sroberto *  the type 'l' (Local Clock) and you should check this with
740258945Sroberto *  ntpq_get_assoc_clocktype for each association, before you use this function
741258945Sroberto *  on it.
742258945Sroberto *
743258945Sroberto ****************************************************************************
744258945Sroberto * Parameters:
745258945Sroberto *	associd		int	requested associaton ID
746258945Sroberto *
747258945Sroberto * Returns:
748258945Sroberto *	int		1 (one) if the clockvars have been read
749258945Sroberto * 			- OR -
750258945Sroberto *			0 (zero) if an error occured and the variable set
751258945Sroberto *			could not be read
752258945Sroberto ****************************************************************************/
753258945Srobertoint  ntpq_get_assoc_clockvars( associd_t associd )
754258945Sroberto{
755258945Sroberto	if (NTP_CLOCKTYPE_LOCAL != ntpq_get_assoc_clocktype(
756258945Sroberto	    ntpq_get_assoc_number(associd)))
757258945Sroberto		return 0;
758258945Sroberto	clockvarlen = ntpq_read_assoc_clockvars( associd, clockvars,
759258945Sroberto						 sizeof(clockvars) );
760258945Sroberto	if ( clockvarlen <= 0 ) {
761258945Sroberto		clockvar_assoc = 0;
762258945Sroberto		return 0;
763258945Sroberto	} else {
764258945Sroberto		clockvar_assoc = associd;
765258945Sroberto		return 1;
766258945Sroberto	}
767258945Sroberto}
768258945Sroberto
769258945Sroberto
770