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