xref: /netbsd-src/external/bsd/ntp/dist/ntpq/libntpq.c (revision cdfa2a7ef92791ba9db70a584a1d904730e6fb46)
1*cdfa2a7eSchristos /*	$NetBSD: libntpq.c,v 1.6 2020/05/25 20:47:26 christos Exp $	*/
2abb0f93cSkardel 
3abb0f93cSkardel /*****************************************************************************
4abb0f93cSkardel  *
5abb0f93cSkardel  *  libntpq.c
6abb0f93cSkardel  *
7abb0f93cSkardel  *  This is the wrapper library for ntpq, the NTP query utility.
8abb0f93cSkardel  *  This library reuses the sourcecode from ntpq and exports a number
9abb0f93cSkardel  *  of useful functions in a library that can be linked against applications
10abb0f93cSkardel  *  that need to query the status of a running ntpd. The whole
11abb0f93cSkardel  *  communcation is based on mode 6 packets.
12abb0f93cSkardel  *
13abb0f93cSkardel  ****************************************************************************/
14f003fb54Skardel #define LIBNTPQ_C
15abb0f93cSkardel #define NO_MAIN_ALLOWED 1
16abb0f93cSkardel /* #define BUILD_AS_LIB		Already provided by the Makefile */
17abb0f93cSkardel 
18abb0f93cSkardel #include "ntpq.c"
19abb0f93cSkardel #include "libntpq.h"
20abb0f93cSkardel 
21abb0f93cSkardel /* Function Prototypes */
22abb0f93cSkardel 
23abb0f93cSkardel 
24abb0f93cSkardel const char *Version = "libntpq 0.3beta";
25abb0f93cSkardel 
26abb0f93cSkardel /* global variables used for holding snapshots of data */
27abb0f93cSkardel char peervars[NTPQ_BUFLEN];
28abb0f93cSkardel int peervarlen = 0;
29f003fb54Skardel associd_t peervar_assoc = 0;
30abb0f93cSkardel char clockvars[NTPQ_BUFLEN];
31abb0f93cSkardel int clockvarlen = 0;
32abb0f93cSkardel int clockvar_assoc = 0;
33abb0f93cSkardel char sysvars[NTPQ_BUFLEN];
34abb0f93cSkardel int sysvarlen = 0;
35abb0f93cSkardel char *ntpq_resultbuffer[NTPQ_BUFLEN];
36abb0f93cSkardel unsigned short ntpq_associations[MAXASSOC];
37abb0f93cSkardel struct ntpq_varlist ntpq_varlist[MAXLIST];
38abb0f93cSkardel 
39abb0f93cSkardel /*****************************************************************************
40abb0f93cSkardel  *
41abb0f93cSkardel  *  ntpq_stripquotes
42abb0f93cSkardel  *
43abb0f93cSkardel  *  Parses a given character buffer srcbuf and removes all quoted
44abb0f93cSkardel  *  characters. The resulting string is copied to the specified
45abb0f93cSkardel  *  resultbuf character buffer.  E.g. \" will be translated into "
46abb0f93cSkardel  *
47abb0f93cSkardel  ****************************************************************************
48abb0f93cSkardel  * Parameters:
49abb0f93cSkardel  *	resultbuf	char*	The resulting string without quoted
50abb0f93cSkardel  *				characters
51abb0f93cSkardel  *	srcbuf		char*	The buffer holding the original string
52abb0f93cSkardel  *	datalen		int	The number of bytes stored in srcbuf
53abb0f93cSkardel  *	maxlen		int	Max. number of bytes for resultbuf
54abb0f93cSkardel  *
55abb0f93cSkardel  * Returns:
56abb0f93cSkardel  *	int		number of chars that have been copied to
57abb0f93cSkardel  *			resultbuf
58abb0f93cSkardel  ****************************************************************************/
59abb0f93cSkardel 
ntpq_stripquotes(char * resultbuf,char * srcbuf,int datalen,int maxlen)60abb0f93cSkardel int ntpq_stripquotes ( char *resultbuf, char *srcbuf, int datalen, int maxlen )
61abb0f93cSkardel {
62ccc794f0Schristos 	char* dst = resultbuf;
63ccc794f0Schristos 	char* dep = resultbuf + maxlen - 1;
64ccc794f0Schristos 	char* src = srcbuf;
65ccc794f0Schristos 	char* sep = srcbuf + (datalen >= 0 ? datalen : 0);
66ccc794f0Schristos 	int   esc = 0;
67ccc794f0Schristos 	int   ch;
68abb0f93cSkardel 
69ccc794f0Schristos 	if (maxlen <= 0)
70ccc794f0Schristos 		return 0;
71abb0f93cSkardel 
72ccc794f0Schristos 	while ((dst != dep) && (src != sep) && (ch = (u_char)*src++) != 0) {
73ccc794f0Schristos 		if (esc) {
74ccc794f0Schristos 			esc = 0;
75ccc794f0Schristos 			switch (ch) {
76abb0f93cSkardel 				/* skip and do not copy */
77ccc794f0Schristos 				/* case '"':*/ /* quotes */
78abb0f93cSkardel 			case 'n': /*newline*/
79abb0f93cSkardel 			case 'r': /*carriage return*/
80abb0f93cSkardel 			case 'g': /*bell*/
81abb0f93cSkardel 			case 't': /*tab*/
82abb0f93cSkardel 				continue;
83ccc794f0Schristos 			default:
84ccc794f0Schristos 				break;
85ccc794f0Schristos 			}
86ccc794f0Schristos 		} else {
87ccc794f0Schristos 			switch (ch) {
88ccc794f0Schristos 			case '\\':
89ccc794f0Schristos 				esc = 1;
90ccc794f0Schristos 			case '"':
91ccc794f0Schristos 				continue;
92ccc794f0Schristos 			default:
93ccc794f0Schristos 				break;
94abb0f93cSkardel 			}
95abb0f93cSkardel 		}
96ccc794f0Schristos 		*dst++ = (char)ch;
97abb0f93cSkardel 	}
98ccc794f0Schristos 	*dst = '\0';
99ccc794f0Schristos 	return (int)(dst - resultbuf);
100abb0f93cSkardel }
101abb0f93cSkardel 
102abb0f93cSkardel 
103abb0f93cSkardel /*****************************************************************************
104abb0f93cSkardel  *
105abb0f93cSkardel  *  ntpq_getvar
106abb0f93cSkardel  *
107abb0f93cSkardel  *  This function parses a given buffer for a variable/value pair and
108abb0f93cSkardel  *  copies the value of the requested variable into the specified
109abb0f93cSkardel  *  varvalue buffer.
110abb0f93cSkardel  *
111abb0f93cSkardel  *  It returns the number of bytes copied or zero for an empty result
112abb0f93cSkardel  *  (=no matching variable found or empty value)
113abb0f93cSkardel  *
114abb0f93cSkardel  ****************************************************************************
115abb0f93cSkardel  * Parameters:
116abb0f93cSkardel  *	resultbuf	char*	The resulting string without quoted
117abb0f93cSkardel  *				characters
118f003fb54Skardel  *	datalen		size_t	The number of bytes stored in
119abb0f93cSkardel  *							resultbuf
120abb0f93cSkardel  *	varname		char*	Name of the required variable
121abb0f93cSkardel  *	varvalue	char*	Where the value of the variable should
122abb0f93cSkardel  *							be stored
123f003fb54Skardel  *	maxlen		size_t	Max. number of bytes for varvalue
124abb0f93cSkardel  *
125abb0f93cSkardel  * Returns:
126f003fb54Skardel  *	size_t		number of chars that have been copied to
127abb0f93cSkardel  *			varvalue
128abb0f93cSkardel  ****************************************************************************/
129abb0f93cSkardel 
130f003fb54Skardel size_t
ntpq_getvar(const char * resultbuf,size_t datalen,const char * varname,char * varvalue,size_t maxlen)131f003fb54Skardel ntpq_getvar(
132f003fb54Skardel 	const char *	resultbuf,
133f003fb54Skardel 	size_t		datalen,
134f003fb54Skardel 	const char *	varname,
135f003fb54Skardel 	char *		varvalue,
136f003fb54Skardel 	size_t		maxlen)
137abb0f93cSkardel {
138abb0f93cSkardel 	char *	name;
139f003fb54Skardel 	char *	value;
1408b8da087Schristos 	size_t	idatalen;
141abb0f93cSkardel 
142f003fb54Skardel 	value = NULL;
143f003fb54Skardel 	idatalen = (int)datalen;
144abb0f93cSkardel 
145f003fb54Skardel 	while (nextvar(&idatalen, &resultbuf, &name, &value)) {
146abb0f93cSkardel 		if (strcmp(varname, name) == 0) {
147abb0f93cSkardel 			ntpq_stripquotes(varvalue, value, strlen(value), maxlen);
148f003fb54Skardel 
149abb0f93cSkardel 			return strlen(varvalue);
150abb0f93cSkardel 		}
151abb0f93cSkardel 	}
152abb0f93cSkardel 
153abb0f93cSkardel 	return 0;
154abb0f93cSkardel }
155abb0f93cSkardel 
156abb0f93cSkardel 
157abb0f93cSkardel /*****************************************************************************
158abb0f93cSkardel  *
159abb0f93cSkardel  *  ntpq_queryhost
160abb0f93cSkardel  *
161abb0f93cSkardel  *  Sends a mode 6 query packet to the current open host (see
162abb0f93cSkardel  *  ntpq_openhost) and stores the requested variable set in the specified
163abb0f93cSkardel  *  character buffer.
164abb0f93cSkardel  *  It returns the number of bytes read or zero for an empty result
165abb0f93cSkardel  *  (=no answer or empty value)
166abb0f93cSkardel  *
167abb0f93cSkardel  ****************************************************************************
168abb0f93cSkardel  * Parameters:
169abb0f93cSkardel  *      VARSET		u_short	Which variable set should be
170abb0f93cSkardel  *				read (PEERVARS or CLOCKVARS)
171abb0f93cSkardel  *	association	int	The association ID that should be read
172abb0f93cSkardel  *				0 represents the ntpd instance itself
173abb0f93cSkardel  *	resultbuf	char*	The resulting string without quoted
174abb0f93cSkardel  *				characters
175abb0f93cSkardel  *	maxlen		int	Max. number of bytes for varvalue
176abb0f93cSkardel  *
177abb0f93cSkardel  * Returns:
178abb0f93cSkardel  *	int		number of bytes that have been copied to
179abb0f93cSkardel  *			resultbuf
180abb0f93cSkardel  *  			- OR -
181abb0f93cSkardel  *			0 (zero) if no reply has been received or
182abb0f93cSkardel  *			another failure occured
183abb0f93cSkardel  ****************************************************************************/
184abb0f93cSkardel 
ntpq_queryhost(unsigned short VARSET,unsigned short association,char * resultbuf,int maxlen)185abb0f93cSkardel int ntpq_queryhost(unsigned short VARSET, unsigned short association, char *resultbuf, int maxlen)
186abb0f93cSkardel {
187f003fb54Skardel 	const char *datap;
188abb0f93cSkardel 	int res;
1898b8da087Schristos 	size_t	dsize;
190abb0f93cSkardel 	u_short	rstatus;
191abb0f93cSkardel 
192abb0f93cSkardel 	if ( numhosts > 0 )
193abb0f93cSkardel 		res = doquery(VARSET,association,0,0, (char *)0, &rstatus, &dsize, &datap);
194abb0f93cSkardel 	else
195abb0f93cSkardel 		return 0;
196abb0f93cSkardel 
197abb0f93cSkardel 	if ( ( res != 0) || ( dsize == 0 ) ) /* no data */
198abb0f93cSkardel 		return 0;
199abb0f93cSkardel 
200abb0f93cSkardel 	if ( dsize > maxlen)
201abb0f93cSkardel 		dsize = maxlen;
202abb0f93cSkardel 
203abb0f93cSkardel 
204abb0f93cSkardel 	/* fill result resultbuf */
205abb0f93cSkardel 	memcpy(resultbuf, datap, dsize);
206abb0f93cSkardel 
207abb0f93cSkardel 	return dsize;
208abb0f93cSkardel }
209abb0f93cSkardel 
210abb0f93cSkardel 
211abb0f93cSkardel 
212abb0f93cSkardel /*****************************************************************************
213abb0f93cSkardel  *
214abb0f93cSkardel  *  ntpq_openhost
215abb0f93cSkardel  *
216abb0f93cSkardel  *  Sets up a connection to the ntpd instance of a specified host. Note:
217abb0f93cSkardel  *  There is no real "connection" established because NTP solely works
218abb0f93cSkardel  *  based on UDP.
219abb0f93cSkardel  *
220abb0f93cSkardel  ****************************************************************************
221abb0f93cSkardel  * Parameters:
222abb0f93cSkardel  *	hostname	char*	Hostname/IP of the host running ntpd
2238585484eSchristos  *	fam		int	Address Family (AF_INET, AF_INET6, or 0)
224abb0f93cSkardel  *
225abb0f93cSkardel  * Returns:
226abb0f93cSkardel  *	int		1 if the host connection could be set up, i.e.
227abb0f93cSkardel  *			name resolution was succesful and/or IP address
228abb0f93cSkardel  *			has been validated
229abb0f93cSkardel  *  			- OR -
230abb0f93cSkardel  *			0 (zero) if a failure occured
231abb0f93cSkardel  ****************************************************************************/
232abb0f93cSkardel 
2338585484eSchristos int
ntpq_openhost(char * hostname,int fam)2348585484eSchristos ntpq_openhost(
2358585484eSchristos 	char *hostname,
2368585484eSchristos 	int fam
2378585484eSchristos 	)
238abb0f93cSkardel {
2398585484eSchristos 	if ( openhost(hostname, fam) )
240abb0f93cSkardel 	{
241abb0f93cSkardel 		numhosts = 1;
242abb0f93cSkardel 	} else {
243abb0f93cSkardel 		numhosts = 0;
244abb0f93cSkardel 	}
245abb0f93cSkardel 
246abb0f93cSkardel 	return numhosts;
247abb0f93cSkardel 
248abb0f93cSkardel }
249abb0f93cSkardel 
250abb0f93cSkardel 
251abb0f93cSkardel /*****************************************************************************
252abb0f93cSkardel  *
253abb0f93cSkardel  *  ntpq_closehost
254abb0f93cSkardel  *
255abb0f93cSkardel  *  Cleans up a connection by closing the used socket. Should be called
256abb0f93cSkardel  *  when no further queries are required for the currently used host.
257abb0f93cSkardel  *
258abb0f93cSkardel  ****************************************************************************
259abb0f93cSkardel  * Parameters:
260abb0f93cSkardel  *	- none -
261abb0f93cSkardel  *
262abb0f93cSkardel  * Returns:
263abb0f93cSkardel  *	int		0 (zero) if no host has been opened before
264abb0f93cSkardel  *			- OR -
265abb0f93cSkardel  *			the resultcode from the closesocket function call
266abb0f93cSkardel  ****************************************************************************/
267abb0f93cSkardel 
ntpq_closehost(void)268abb0f93cSkardel int ntpq_closehost(void)
269abb0f93cSkardel {
270abb0f93cSkardel 	if ( numhosts )
271abb0f93cSkardel 	 return closesocket(sockfd);
272abb0f93cSkardel 
273abb0f93cSkardel 	return 0;
274abb0f93cSkardel }
275abb0f93cSkardel 
276abb0f93cSkardel 
277abb0f93cSkardel /*****************************************************************************
278abb0f93cSkardel  *
279abb0f93cSkardel  *  ntpq_read_associations
280abb0f93cSkardel  *
281abb0f93cSkardel  *  This function queries the ntp host for its associations and returns the
282abb0f93cSkardel  *  number of associations found.
283abb0f93cSkardel  *
284abb0f93cSkardel  *  It takes an u_short array as its first parameter, this array holds the
285abb0f93cSkardel  *  IDs of the associations,
286abb0f93cSkardel  *  the function will not write more entries than specified with the
287abb0f93cSkardel  *  max_entries parameter.
288abb0f93cSkardel  *
289abb0f93cSkardel  *  However, if more than max_entries associations were found, the return
290abb0f93cSkardel  *  value of this function will reflect the real number, even if not all
291abb0f93cSkardel  *  associations have been stored in the array.
292abb0f93cSkardel  *
293abb0f93cSkardel  ****************************************************************************
294abb0f93cSkardel  * Parameters:
295abb0f93cSkardel  *	resultbuf	u_short*Array that should hold the list of
296abb0f93cSkardel  *				association IDs
297abb0f93cSkardel  *	maxentries	int	maximum number of association IDs that can
298abb0f93cSkardel  *				be stored in resultbuf
299abb0f93cSkardel  *
300abb0f93cSkardel  * Returns:
301abb0f93cSkardel  *	int		number of association IDs stored in resultbuf
302abb0f93cSkardel  *  			- OR -
303abb0f93cSkardel  *			0 (zero) if a failure occured or no association has
304abb0f93cSkardel  *			been returned.
305abb0f93cSkardel  ****************************************************************************/
306abb0f93cSkardel 
ntpq_read_associations(u_short resultbuf[],int max_entries)307abb0f93cSkardel  int  ntpq_read_associations ( u_short resultbuf[], int max_entries )
308abb0f93cSkardel {
309abb0f93cSkardel     int i = 0;
310abb0f93cSkardel 
311abb0f93cSkardel     if (ntpq_dogetassoc()) {
312abb0f93cSkardel 
313abb0f93cSkardel         if(numassoc < max_entries)
314abb0f93cSkardel           max_entries = numassoc;
315abb0f93cSkardel 
316abb0f93cSkardel         for (i=0;i<max_entries;i++)
317abb0f93cSkardel             resultbuf[i] = assoc_cache[i].assid;
318abb0f93cSkardel 
319abb0f93cSkardel         return numassoc;
320abb0f93cSkardel     }
321abb0f93cSkardel 
322abb0f93cSkardel     return 0;
323abb0f93cSkardel }
324abb0f93cSkardel 
325abb0f93cSkardel 
326abb0f93cSkardel 
327abb0f93cSkardel 
328abb0f93cSkardel /*****************************************************************************
329abb0f93cSkardel  *
330abb0f93cSkardel  *  ntpq_get_assocs
331abb0f93cSkardel  *
332abb0f93cSkardel  *  This function reads the associations of a previously selected (with
333abb0f93cSkardel  *  ntpq_openhost) NTP host into its own (global) array and returns the
334abb0f93cSkardel  *  number of associations found.
335abb0f93cSkardel  *
336abb0f93cSkardel  *  The obtained association IDs can be read by using the ntpq_get_assoc_id
337abb0f93cSkardel  *  function.
338abb0f93cSkardel  *
339abb0f93cSkardel  ****************************************************************************
340abb0f93cSkardel  * Parameters:
341abb0f93cSkardel  *	- none -
342abb0f93cSkardel  *
343abb0f93cSkardel  * Returns:
344abb0f93cSkardel  *	int		number of association IDs stored in resultbuf
345abb0f93cSkardel  *  			- OR -
346abb0f93cSkardel  *			0 (zero) if a failure occured or no association has
347abb0f93cSkardel  *			been returned.
348abb0f93cSkardel  ****************************************************************************/
349abb0f93cSkardel 
ntpq_get_assocs(void)350abb0f93cSkardel  int  ntpq_get_assocs ( void )
351abb0f93cSkardel {
352abb0f93cSkardel     return ntpq_read_associations( ntpq_associations, MAXASSOC );
353abb0f93cSkardel }
354abb0f93cSkardel 
355abb0f93cSkardel 
356abb0f93cSkardel /*****************************************************************************
357abb0f93cSkardel  *
358abb0f93cSkardel  *  ntpq_get_assoc_number
359abb0f93cSkardel  *
360abb0f93cSkardel  *  This function returns for a given Association ID the association number
361abb0f93cSkardel  *  in the internal association array, which is filled by the ntpq_get_assocs
362abb0f93cSkardel  *  function.
363abb0f93cSkardel  *
364abb0f93cSkardel  ****************************************************************************
365abb0f93cSkardel  * Parameters:
366abb0f93cSkardel  *	associd		int	requested associaton ID
367abb0f93cSkardel  *
368abb0f93cSkardel  * Returns:
369abb0f93cSkardel  *	int		the number of the association array element that is
370abb0f93cSkardel  *			representing the given association ID
371abb0f93cSkardel  *  			- OR -
372abb0f93cSkardel  *			-1 if a failure occured or no matching association
373abb0f93cSkardel  * 			ID has been found
374abb0f93cSkardel  ****************************************************************************/
375abb0f93cSkardel 
ntpq_get_assoc_number(associd_t associd)376f003fb54Skardel int ntpq_get_assoc_number ( associd_t associd )
377abb0f93cSkardel {
378f003fb54Skardel 	int i;
379abb0f93cSkardel 
380abb0f93cSkardel 	for (i=0;i<numassoc;i++) {
381abb0f93cSkardel 		if (assoc_cache[i].assid == associd)
382abb0f93cSkardel 			return i;
383abb0f93cSkardel 	}
384abb0f93cSkardel 
385f003fb54Skardel 	return -1;
386abb0f93cSkardel 
387abb0f93cSkardel }
388abb0f93cSkardel 
389abb0f93cSkardel 
390abb0f93cSkardel /*****************************************************************************
391abb0f93cSkardel  *
392abb0f93cSkardel  *  ntpq_read_assoc_peervars
393abb0f93cSkardel  *
394abb0f93cSkardel  *  This function reads the peervars variable-set of a specified association
395abb0f93cSkardel  *  from a NTP host and writes it to the result buffer specified, honoring
396abb0f93cSkardel  *  the maxsize limit.
397abb0f93cSkardel  *
398abb0f93cSkardel  *  It returns the number of bytes written or 0 when the variable-set is
399abb0f93cSkardel  *  empty or failed to read.
400abb0f93cSkardel  *
401abb0f93cSkardel  ****************************************************************************
402abb0f93cSkardel  * Parameters:
403abb0f93cSkardel  *	associd		int	requested associaton ID
404abb0f93cSkardel  *	resultbuf	char*	character buffer where the variable set
405abb0f93cSkardel  *				should be stored
406abb0f93cSkardel  *	maxsize		int	the maximum number of bytes that can be
407abb0f93cSkardel  *				written to resultbuf
408abb0f93cSkardel  *
409abb0f93cSkardel  * Returns:
410abb0f93cSkardel  *	int		number of chars that have been copied to
411abb0f93cSkardel  *			resultbuf
412abb0f93cSkardel  *			- OR -
413abb0f93cSkardel  *			0 (zero) if an error occured
414abb0f93cSkardel  ****************************************************************************/
415abb0f93cSkardel 
416f003fb54Skardel int
ntpq_read_assoc_peervars(associd_t associd,char * resultbuf,int maxsize)417f003fb54Skardel ntpq_read_assoc_peervars(
418f003fb54Skardel 	associd_t	associd,
419f003fb54Skardel 	char *		resultbuf,
420f003fb54Skardel 	int		maxsize
421f003fb54Skardel 	)
422abb0f93cSkardel {
423f003fb54Skardel 	const char *	datap;
424abb0f93cSkardel 	int		res;
4258b8da087Schristos 	size_t		dsize;
426abb0f93cSkardel 	u_short		rstatus;
427abb0f93cSkardel 
428f003fb54Skardel 	res = doquery(CTL_OP_READVAR, associd, 0, 0, NULL, &rstatus,
429abb0f93cSkardel 		      &dsize, &datap);
430abb0f93cSkardel 	if (res != 0)
431abb0f93cSkardel 		return 0;
432f003fb54Skardel 	if (dsize <= 0) {
433abb0f93cSkardel 		if (numhosts > 1)
434f003fb54Skardel 			fprintf(stderr, "server=%s ", currenthost);
435f003fb54Skardel 		fprintf(stderr,
436abb0f93cSkardel 			"***No information returned for association %d\n",
437abb0f93cSkardel 			associd);
438f003fb54Skardel 
439abb0f93cSkardel 		return 0;
440f003fb54Skardel 	}
441abb0f93cSkardel 	if (dsize > maxsize)
442abb0f93cSkardel 		dsize = maxsize;
443abb0f93cSkardel 	memcpy(resultbuf, datap, dsize);
444abb0f93cSkardel 
445abb0f93cSkardel 	return dsize;
446abb0f93cSkardel }
447abb0f93cSkardel 
448abb0f93cSkardel 
449abb0f93cSkardel 
450abb0f93cSkardel 
451abb0f93cSkardel /*****************************************************************************
452abb0f93cSkardel  *
453abb0f93cSkardel  *  ntpq_read_sysvars
454abb0f93cSkardel  *
455abb0f93cSkardel  *  This function reads the sysvars variable-set from a NTP host and writes it
456abb0f93cSkardel  *  to the result buffer specified, honoring the maxsize limit.
457abb0f93cSkardel  *
458abb0f93cSkardel  *  It returns the number of bytes written or 0 when the variable-set is empty
459abb0f93cSkardel  *  or could not be read.
460abb0f93cSkardel  *
461abb0f93cSkardel  ****************************************************************************
462abb0f93cSkardel  * Parameters:
463abb0f93cSkardel  *	resultbuf	char*	character buffer where the variable set
464abb0f93cSkardel  *				should be stored
465abb0f93cSkardel  *	maxsize		int	the maximum number of bytes that can be
466abb0f93cSkardel  *				written to resultbuf
467abb0f93cSkardel  *
468abb0f93cSkardel  * Returns:
469abb0f93cSkardel  *	int		number of chars that have been copied to
470abb0f93cSkardel  *			resultbuf
471abb0f93cSkardel  *			- OR -
472abb0f93cSkardel  *			0 (zero) if an error occured
473abb0f93cSkardel  ****************************************************************************/
474f003fb54Skardel size_t
ntpq_read_sysvars(char * resultbuf,size_t maxsize)475f003fb54Skardel ntpq_read_sysvars(
476f003fb54Skardel 	char *	resultbuf,
477f003fb54Skardel 	size_t	maxsize
478f003fb54Skardel 	)
479abb0f93cSkardel {
480f003fb54Skardel 	const char *	datap;
481abb0f93cSkardel 	int		res;
482f003fb54Skardel 	size_t		dsize;
483abb0f93cSkardel 	u_short		rstatus;
484abb0f93cSkardel 
485f003fb54Skardel 	res = doquery(CTL_OP_READVAR, 0, 0, 0, NULL, &rstatus,
4868b8da087Schristos 		      &dsize, &datap);
487abb0f93cSkardel 
488abb0f93cSkardel 	if (res != 0)
489abb0f93cSkardel 		return 0;
490abb0f93cSkardel 
4918b8da087Schristos 	if (dsize == 0) {
492abb0f93cSkardel 		if (numhosts > 1)
493f003fb54Skardel 			fprintf(stderr, "server=%s ", currenthost);
494f003fb54Skardel 		fprintf(stderr, "***No sysvar information returned\n");
495f003fb54Skardel 
496abb0f93cSkardel 		return 0;
497abb0f93cSkardel 	} else {
498f003fb54Skardel 		dsize = min(dsize, maxsize);
499abb0f93cSkardel 		memcpy(resultbuf, datap, dsize);
500abb0f93cSkardel 	}
501abb0f93cSkardel 
502abb0f93cSkardel 	return dsize;
503abb0f93cSkardel }
504abb0f93cSkardel 
505abb0f93cSkardel 
506abb0f93cSkardel /*****************************************************************************
507abb0f93cSkardel  *  ntpq_get_assoc_allvars
508abb0f93cSkardel  *
509abb0f93cSkardel  *  With this function all association variables for the specified association
510abb0f93cSkardel  *  ID can be requested from a NTP host. They are stored internally and can be
511abb0f93cSkardel  *  read by using the ntpq_get_peervar or ntpq_get_clockvar functions.
512abb0f93cSkardel  *
513abb0f93cSkardel  *  Basically this is only a combination of the ntpq_get_assoc_peervars and
514abb0f93cSkardel  *  ntpq_get_assoc_clockvars functions.
515abb0f93cSkardel  *
516abb0f93cSkardel  *  It returns 1 if both variable-sets (peervars and clockvars) were
517abb0f93cSkardel  *  received successfully. If one variable-set or both of them weren't
518abb0f93cSkardel  *  received,
519abb0f93cSkardel  *
520abb0f93cSkardel  ****************************************************************************
521abb0f93cSkardel  * Parameters:
522abb0f93cSkardel  *	associd		int	requested associaton ID
523abb0f93cSkardel  *
524abb0f93cSkardel  * Returns:
525abb0f93cSkardel  *	int		nonzero if at least one variable set could be read
526abb0f93cSkardel  * 			- OR -
527abb0f93cSkardel  *			0 (zero) if an error occured and both variable sets
528abb0f93cSkardel  *			could not be read
529abb0f93cSkardel  ****************************************************************************/
ntpq_get_assoc_allvars(associd_t associd)530f003fb54Skardel  int  ntpq_get_assoc_allvars( associd_t associd  )
531abb0f93cSkardel {
532f003fb54Skardel 	return ntpq_get_assoc_peervars ( associd ) &
533f003fb54Skardel 	       ntpq_get_assoc_clockvars( associd );
534abb0f93cSkardel }
535abb0f93cSkardel 
536abb0f93cSkardel 
537abb0f93cSkardel 
538abb0f93cSkardel 
539abb0f93cSkardel /*****************************************************************************
540abb0f93cSkardel  *
541abb0f93cSkardel  *  ntpq_get_sysvars
542abb0f93cSkardel  *
543abb0f93cSkardel  *  The system variables of a NTP host can be requested by using this function
544abb0f93cSkardel  *  and afterwards using ntpq_get_sysvar to read the single variable values.
545abb0f93cSkardel  *
546abb0f93cSkardel  ****************************************************************************
547abb0f93cSkardel  * Parameters:
548abb0f93cSkardel  *	- none -
549abb0f93cSkardel  *
550abb0f93cSkardel  * Returns:
551abb0f93cSkardel  *	int		nonzero if the variable set could be read
552abb0f93cSkardel  * 			- OR -
553abb0f93cSkardel  *			0 (zero) if an error occured and the sysvars
554abb0f93cSkardel  *			could not be read
555abb0f93cSkardel  ****************************************************************************/
556f003fb54Skardel int
ntpq_get_sysvars(void)557f003fb54Skardel ntpq_get_sysvars(void)
558abb0f93cSkardel {
559f003fb54Skardel 	sysvarlen = ntpq_read_sysvars(sysvars, sizeof(sysvars));
560f003fb54Skardel 	if (sysvarlen <= 0)
561abb0f93cSkardel 		return 0;
562f003fb54Skardel 	else
563abb0f93cSkardel 		return 1;
564abb0f93cSkardel }
565abb0f93cSkardel 
566abb0f93cSkardel 
567abb0f93cSkardel /*****************************************************************************
568abb0f93cSkardel  *
569abb0f93cSkardel  *  ntp_get_peervar
570abb0f93cSkardel  *
571abb0f93cSkardel  *  This function uses the variable-set which was read by using
572abb0f93cSkardel  *  ntp_get_peervars and searches for a variable specified with varname. If
573abb0f93cSkardel  *  such a variable exists, it writes its value into
574abb0f93cSkardel  *  varvalue (maxlen specifies the size of this target buffer).
575abb0f93cSkardel  *
576abb0f93cSkardel  ****************************************************************************
577abb0f93cSkardel  * Parameters:
578abb0f93cSkardel  *	varname		char*	requested variable name
579abb0f93cSkardel  *	varvalue	char*	the buffer where the value should go into
580abb0f93cSkardel  *	maxlen		int	maximum number of bytes that can be copied to
581abb0f93cSkardel  *				varvalue
582abb0f93cSkardel  *
583abb0f93cSkardel  * Returns:
584abb0f93cSkardel  *	int		number of bytes copied to varvalue
585abb0f93cSkardel  * 			- OR -
586abb0f93cSkardel  *			0 (zero) if an error occured or the variable could
587abb0f93cSkardel  *			not be found
588abb0f93cSkardel  ****************************************************************************/
ntpq_get_peervar(const char * varname,char * varvalue,int maxlen)589abb0f93cSkardel int ntpq_get_peervar( const char *varname, char *varvalue, int maxlen)
590abb0f93cSkardel {
591abb0f93cSkardel     return ( ntpq_getvar(peervars,peervarlen,varname,varvalue,maxlen) );
592abb0f93cSkardel }
593abb0f93cSkardel 
594abb0f93cSkardel 
595abb0f93cSkardel 
596abb0f93cSkardel /*****************************************************************************
597abb0f93cSkardel  *
598abb0f93cSkardel  *  ntpq_get_assoc_peervars
599abb0f93cSkardel  *
600abb0f93cSkardel  *  This function requests the peer variables of the specified association
601abb0f93cSkardel  *  from a NTP host. In order to access the variable values, the function
602abb0f93cSkardel  *  ntpq_get_peervar must be used.
603abb0f93cSkardel  *
604abb0f93cSkardel  ****************************************************************************
605abb0f93cSkardel  * Parameters:
606abb0f93cSkardel  *	associd		int	requested associaton ID
607abb0f93cSkardel  *
608abb0f93cSkardel  * Returns:
609abb0f93cSkardel  *	int		1 (one) if the peervars have been read
610abb0f93cSkardel  * 			- OR -
611abb0f93cSkardel  *			0 (zero) if an error occured and the variable set
612abb0f93cSkardel  *			could not be read
613abb0f93cSkardel  ****************************************************************************/
614f003fb54Skardel int
ntpq_get_assoc_peervars(associd_t associd)615f003fb54Skardel ntpq_get_assoc_peervars(
616f003fb54Skardel 	associd_t associd
617f003fb54Skardel 	)
618abb0f93cSkardel {
619f003fb54Skardel 	peervarlen = ntpq_read_assoc_peervars(associd, peervars,
620f003fb54Skardel 					      sizeof(peervars));
621abb0f93cSkardel 	if (peervarlen <= 0) {
622abb0f93cSkardel 		peervar_assoc = 0;
623f003fb54Skardel 
624abb0f93cSkardel 		return 0;
625abb0f93cSkardel 	}
626f003fb54Skardel 	peervar_assoc = associd;
627f003fb54Skardel 
628f003fb54Skardel 	return 1;
629abb0f93cSkardel }
630abb0f93cSkardel 
631abb0f93cSkardel 
632abb0f93cSkardel /*****************************************************************************
633abb0f93cSkardel  *
634abb0f93cSkardel  *  ntp_read_assoc_clockvars
635abb0f93cSkardel  *
636abb0f93cSkardel  *  This function reads the clockvars variable-set of a specified association
637abb0f93cSkardel  *  from a NTP host and writes it to the result buffer specified, honoring
638abb0f93cSkardel  *  the maxsize limit.
639abb0f93cSkardel  *
640abb0f93cSkardel  *  It returns the number of bytes written or 0 when the variable-set is
641abb0f93cSkardel  *  empty or failed to read.
642abb0f93cSkardel  *
643abb0f93cSkardel  ****************************************************************************
644abb0f93cSkardel  * Parameters:
645abb0f93cSkardel  *	associd		int	requested associaton ID
646abb0f93cSkardel  *	resultbuf	char*	character buffer where the variable set
647abb0f93cSkardel  *				should be stored
648abb0f93cSkardel  *	maxsize		int	the maximum number of bytes that can be
649abb0f93cSkardel  *				written to resultbuf
650abb0f93cSkardel  *
651abb0f93cSkardel  * Returns:
652abb0f93cSkardel  *	int		number of chars that have been copied to
653abb0f93cSkardel  *			resultbuf
654abb0f93cSkardel  *			- OR -
655abb0f93cSkardel  *			0 (zero) if an error occured
656abb0f93cSkardel  ****************************************************************************/
657abb0f93cSkardel 
658f003fb54Skardel int
ntpq_read_assoc_clockvars(associd_t associd,char * resultbuf,int maxsize)659f003fb54Skardel ntpq_read_assoc_clockvars(
660f003fb54Skardel 	associd_t	associd,
661f003fb54Skardel 	char *		resultbuf,
662f003fb54Skardel 	int		maxsize
663f003fb54Skardel 	)
664abb0f93cSkardel {
665f003fb54Skardel 	const char *datap;
666abb0f93cSkardel 	int res;
6678b8da087Schristos 	size_t dsize;
668abb0f93cSkardel 	u_short rstatus;
669abb0f93cSkardel 
670f003fb54Skardel 	res = ntpq_doquerylist(ntpq_varlist, CTL_OP_READCLOCK, associd,
671f003fb54Skardel 			       0, &rstatus, &dsize, &datap);
672abb0f93cSkardel 	if (res != 0)
673abb0f93cSkardel 		return 0;
674abb0f93cSkardel 
675abb0f93cSkardel 	if (dsize == 0) {
676abb0f93cSkardel 		if (numhosts > 1) /* no information returned from server */
677abb0f93cSkardel 			return 0;
678abb0f93cSkardel 	} else {
679abb0f93cSkardel 		if (dsize > maxsize)
680abb0f93cSkardel 			dsize = maxsize;
681abb0f93cSkardel 		memcpy(resultbuf, datap, dsize);
682abb0f93cSkardel 	}
683abb0f93cSkardel 
684abb0f93cSkardel 	return dsize;
685abb0f93cSkardel }
686abb0f93cSkardel 
687abb0f93cSkardel 
688abb0f93cSkardel 
689abb0f93cSkardel /*****************************************************************************
690abb0f93cSkardel  *
691abb0f93cSkardel  *  ntpq_get_assoc_clocktype
692abb0f93cSkardel  *
693abb0f93cSkardel  *  This function returns a clocktype value for a given association number
694abb0f93cSkardel  *  (not ID!):
695abb0f93cSkardel  *
696abb0f93cSkardel  *  NTP_CLOCKTYPE_UNKNOWN   Unknown clock type
697abb0f93cSkardel  *  NTP_CLOCKTYPE_BROADCAST Broadcast server
698abb0f93cSkardel  *  NTP_CLOCKTYPE_LOCAL     Local clock
699abb0f93cSkardel  *  NTP_CLOCKTYPE_UNICAST   Unicast server
700abb0f93cSkardel  *  NTP_CLOCKTYPE_MULTICAST Multicast server
701abb0f93cSkardel  *
702abb0f93cSkardel  ****************************************************************************/
703f003fb54Skardel int
ntpq_get_assoc_clocktype(int assoc_index)704f003fb54Skardel ntpq_get_assoc_clocktype(
705f003fb54Skardel 	int assoc_index
706f003fb54Skardel 	)
707abb0f93cSkardel {
708f003fb54Skardel 	associd_t	associd;
709f003fb54Skardel 	int		i;
710f003fb54Skardel 	int		rc;
711abb0f93cSkardel 	sockaddr_u	dum_store;
712f003fb54Skardel 	char		dstadr[LENHOSTNAME];
713f003fb54Skardel 	char		resultbuf[NTPQ_BUFLEN];
714abb0f93cSkardel 
715f003fb54Skardel 	if (assoc_index < 0 || assoc_index >= numassoc)
716abb0f93cSkardel 		return -1;
717f003fb54Skardel 
718f003fb54Skardel 	associd = assoc_cache[assoc_index].assid;
719f003fb54Skardel 	if (associd == peervar_assoc) {
720f003fb54Skardel 		rc = ntpq_get_peervar("dstadr", dstadr, sizeof(dstadr));
721abb0f93cSkardel 	} else {
722f003fb54Skardel 		i = ntpq_read_assoc_peervars(associd, resultbuf,
723f003fb54Skardel 					     sizeof(resultbuf));
724f003fb54Skardel 		if (i <= 0)
725abb0f93cSkardel 			return -1;
726f003fb54Skardel 		rc = ntpq_getvar(resultbuf, i, "dstadr", dstadr,
727f003fb54Skardel 				 sizeof(dstadr));
728abb0f93cSkardel 	}
729abb0f93cSkardel 
730f003fb54Skardel 	if (0 != rc && decodenetnum(dstadr, &dum_store))
731f003fb54Skardel 		return ntpq_decodeaddrtype(&dum_store);
732abb0f93cSkardel 
733abb0f93cSkardel 	return -1;
734abb0f93cSkardel }
735abb0f93cSkardel 
736abb0f93cSkardel 
737abb0f93cSkardel 
738abb0f93cSkardel /*****************************************************************************
739abb0f93cSkardel  *
740abb0f93cSkardel  *  ntpq_get_assoc_clockvars
741abb0f93cSkardel  *
742abb0f93cSkardel  *  With this function the clock variables of the specified association are
743abb0f93cSkardel  *  requested from a NTP host. This makes only sense for associations with
744abb0f93cSkardel  *  the type 'l' (Local Clock) and you should check this with
745abb0f93cSkardel  *  ntpq_get_assoc_clocktype for each association, before you use this function
746abb0f93cSkardel  *  on it.
747abb0f93cSkardel  *
748abb0f93cSkardel  ****************************************************************************
749abb0f93cSkardel  * Parameters:
750abb0f93cSkardel  *	associd		int	requested associaton ID
751abb0f93cSkardel  *
752abb0f93cSkardel  * Returns:
753abb0f93cSkardel  *	int		1 (one) if the clockvars have been read
754abb0f93cSkardel  * 			- OR -
755abb0f93cSkardel  *			0 (zero) if an error occured and the variable set
756abb0f93cSkardel  *			could not be read
757abb0f93cSkardel  ****************************************************************************/
ntpq_get_assoc_clockvars(associd_t associd)758f003fb54Skardel int  ntpq_get_assoc_clockvars( associd_t associd )
759abb0f93cSkardel {
760f003fb54Skardel 	if (NTP_CLOCKTYPE_LOCAL != ntpq_get_assoc_clocktype(
761f003fb54Skardel 	    ntpq_get_assoc_number(associd)))
762abb0f93cSkardel 		return 0;
763f003fb54Skardel 	clockvarlen = ntpq_read_assoc_clockvars( associd, clockvars,
764f003fb54Skardel 						 sizeof(clockvars) );
765abb0f93cSkardel 	if ( clockvarlen <= 0 ) {
766abb0f93cSkardel 		clockvar_assoc = 0;
767abb0f93cSkardel 		return 0;
768abb0f93cSkardel 	} else {
769abb0f93cSkardel 		clockvar_assoc = associd;
770abb0f93cSkardel 		return 1;
771abb0f93cSkardel 	}
772abb0f93cSkardel }
773abb0f93cSkardel 
774abb0f93cSkardel 
775