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