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