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