diff options
author | Ollivier Robert <roberto@FreeBSD.org> | 2013-12-04 21:33:17 +0000 |
---|---|---|
committer | Ollivier Robert <roberto@FreeBSD.org> | 2013-12-04 21:33:17 +0000 |
commit | 2b45e011ca352ce509bc83ae148230aeee0c7e0d (patch) | |
tree | a618007bb41d13153794a598e3d904ace2976324 /ntpq/libntpq.c | |
parent | 9b5bd0a264b0a21eefac2b929b574c73bd601507 (diff) | |
download | src-2b45e011ca352ce509bc83ae148230aeee0c7e0d.tar.gz src-2b45e011ca352ce509bc83ae148230aeee0c7e0d.zip |
Virgin import of ntpd 4.2.6p5.vendor/ntp/4.2.6p5
When the series of commits is complete, things like
https://cert.litnet.lt/en/docs/ntp-distributed-reflection-dos-attacks
should be fixed.
PR: bin/148836 (except that we import a newer version)
Asked by: Too many
MFC after: 2 weeks
Notes
Notes:
svn path=/vendor/ntp/dist/; revision=258945
svn path=/vendor/ntp/4.2.6p5/; revision=258946; tag=vendor/ntp/4.2.6p5
Diffstat (limited to 'ntpq/libntpq.c')
-rw-r--r-- | ntpq/libntpq.c | 766 |
1 files changed, 766 insertions, 0 deletions
diff --git a/ntpq/libntpq.c b/ntpq/libntpq.c new file mode 100644 index 000000000000..fff8e81eab74 --- /dev/null +++ b/ntpq/libntpq.c @@ -0,0 +1,766 @@ +/***************************************************************************** + * + * libntpq.c + * + * This is the wrapper library for ntpq, the NTP query utility. + * This library reuses the sourcecode from ntpq and exports a number + * of useful functions in a library that can be linked against applications + * that need to query the status of a running ntpd. The whole + * communcation is based on mode 6 packets. + * + ****************************************************************************/ +#define LIBNTPQ_C +#define NO_MAIN_ALLOWED 1 +/* #define BUILD_AS_LIB Already provided by the Makefile */ + +#include "ntpq.c" +#include "libntpq.h" + +/* Function Prototypes */ + + +const char *Version = "libntpq 0.3beta"; + +/* global variables used for holding snapshots of data */ +char peervars[NTPQ_BUFLEN]; +int peervarlen = 0; +associd_t peervar_assoc = 0; +char clockvars[NTPQ_BUFLEN]; +int clockvarlen = 0; +int clockvar_assoc = 0; +char sysvars[NTPQ_BUFLEN]; +int sysvarlen = 0; +char *ntpq_resultbuffer[NTPQ_BUFLEN]; +unsigned short ntpq_associations[MAXASSOC]; +struct ntpq_varlist ntpq_varlist[MAXLIST]; + +/***************************************************************************** + * + * ntpq_stripquotes + * + * Parses a given character buffer srcbuf and removes all quoted + * characters. The resulting string is copied to the specified + * resultbuf character buffer. E.g. \" will be translated into " + * + **************************************************************************** + * Parameters: + * resultbuf char* The resulting string without quoted + * characters + * srcbuf char* The buffer holding the original string + * datalen int The number of bytes stored in srcbuf + * maxlen int Max. number of bytes for resultbuf + * + * Returns: + * int number of chars that have been copied to + * resultbuf + ****************************************************************************/ + +int ntpq_stripquotes ( char *resultbuf, char *srcbuf, int datalen, int maxlen ) +{ + char* tmpbuf = srcbuf; + + while ( *tmpbuf != 0 ) + { + if ( *tmpbuf == '\"' ) + { + tmpbuf++; + continue; + } + + if ( *tmpbuf == '\\' ) + { + tmpbuf++; + switch ( *tmpbuf ) + { + /* ignore if end of string */ + case 0: + continue; + /* skip and do not copy */ + case '\"': /* quotes */ + case 'n': /*newline*/ + case 'r': /*carriage return*/ + case 'g': /*bell*/ + case 't': /*tab*/ + tmpbuf++; + continue; + } + } + + *resultbuf++ = *tmpbuf++; + + } + + *resultbuf = 0; + return strlen(resultbuf); +} + + +/***************************************************************************** + * + * ntpq_getvar + * + * This function parses a given buffer for a variable/value pair and + * copies the value of the requested variable into the specified + * varvalue buffer. + * + * It returns the number of bytes copied or zero for an empty result + * (=no matching variable found or empty value) + * + **************************************************************************** + * Parameters: + * resultbuf char* The resulting string without quoted + * characters + * datalen size_t The number of bytes stored in + * resultbuf + * varname char* Name of the required variable + * varvalue char* Where the value of the variable should + * be stored + * maxlen size_t Max. number of bytes for varvalue + * + * Returns: + * size_t number of chars that have been copied to + * varvalue + ****************************************************************************/ + +size_t +ntpq_getvar( + const char * resultbuf, + size_t datalen, + const char * varname, + char * varvalue, + size_t maxlen) +{ + char * name; + char * value; + int idatalen; + + value = NULL; + idatalen = (int)datalen; + + while (nextvar(&idatalen, &resultbuf, &name, &value)) { + if (strcmp(varname, name) == 0) { + ntpq_stripquotes(varvalue, value, strlen(value), maxlen); + + return strlen(varvalue); + } + } + + return 0; +} + + +/***************************************************************************** + * + * ntpq_queryhost + * + * Sends a mode 6 query packet to the current open host (see + * ntpq_openhost) and stores the requested variable set in the specified + * character buffer. + * It returns the number of bytes read or zero for an empty result + * (=no answer or empty value) + * + **************************************************************************** + * Parameters: + * VARSET u_short Which variable set should be + * read (PEERVARS or CLOCKVARS) + * association int The association ID that should be read + * 0 represents the ntpd instance itself + * resultbuf char* The resulting string without quoted + * characters + * maxlen int Max. number of bytes for varvalue + * + * Returns: + * int number of bytes that have been copied to + * resultbuf + * - OR - + * 0 (zero) if no reply has been received or + * another failure occured + ****************************************************************************/ + +int ntpq_queryhost(unsigned short VARSET, unsigned short association, char *resultbuf, int maxlen) +{ + const char *datap; + int res; + int dsize; + u_short rstatus; + + if ( numhosts > 0 ) + res = doquery(VARSET,association,0,0, (char *)0, &rstatus, &dsize, &datap); + else + return 0; + + if ( ( res != 0) || ( dsize == 0 ) ) /* no data */ + return 0; + + if ( dsize > maxlen) + dsize = maxlen; + + + /* fill result resultbuf */ + memcpy(resultbuf, datap, dsize); + + return dsize; +} + + + +/***************************************************************************** + * + * ntpq_openhost + * + * Sets up a connection to the ntpd instance of a specified host. Note: + * There is no real "connection" established because NTP solely works + * based on UDP. + * + **************************************************************************** + * Parameters: + * hostname char* Hostname/IP of the host running ntpd + * + * Returns: + * int 1 if the host connection could be set up, i.e. + * name resolution was succesful and/or IP address + * has been validated + * - OR - + * 0 (zero) if a failure occured + ****************************************************************************/ + +int ntpq_openhost(char *hostname) +{ + if ( openhost(hostname) ) + { + numhosts = 1; + } else { + numhosts = 0; + } + + return numhosts; + +} + + +/***************************************************************************** + * + * ntpq_closehost + * + * Cleans up a connection by closing the used socket. Should be called + * when no further queries are required for the currently used host. + * + **************************************************************************** + * Parameters: + * - none - + * + * Returns: + * int 0 (zero) if no host has been opened before + * - OR - + * the resultcode from the closesocket function call + ****************************************************************************/ + +int ntpq_closehost(void) +{ + if ( numhosts ) + return closesocket(sockfd); + + return 0; +} + + +/***************************************************************************** + * + * ntpq_read_associations + * + * This function queries the ntp host for its associations and returns the + * number of associations found. + * + * It takes an u_short array as its first parameter, this array holds the + * IDs of the associations, + * the function will not write more entries than specified with the + * max_entries parameter. + * + * However, if more than max_entries associations were found, the return + * value of this function will reflect the real number, even if not all + * associations have been stored in the array. + * + **************************************************************************** + * Parameters: + * resultbuf u_short*Array that should hold the list of + * association IDs + * maxentries int maximum number of association IDs that can + * be stored in resultbuf + * + * Returns: + * int number of association IDs stored in resultbuf + * - OR - + * 0 (zero) if a failure occured or no association has + * been returned. + ****************************************************************************/ + + int ntpq_read_associations ( u_short resultbuf[], int max_entries ) +{ + int i = 0; + + if (ntpq_dogetassoc()) { + + if(numassoc < max_entries) + max_entries = numassoc; + + for (i=0;i<max_entries;i++) + resultbuf[i] = assoc_cache[i].assid; + + return numassoc; + } + + return 0; +} + + + + +/***************************************************************************** + * + * ntpq_get_assocs + * + * This function reads the associations of a previously selected (with + * ntpq_openhost) NTP host into its own (global) array and returns the + * number of associations found. + * + * The obtained association IDs can be read by using the ntpq_get_assoc_id + * function. + * + **************************************************************************** + * Parameters: + * - none - + * + * Returns: + * int number of association IDs stored in resultbuf + * - OR - + * 0 (zero) if a failure occured or no association has + * been returned. + ****************************************************************************/ + + int ntpq_get_assocs ( void ) +{ + return ntpq_read_associations( ntpq_associations, MAXASSOC ); +} + + +/***************************************************************************** + * + * ntpq_get_assoc_number + * + * This function returns for a given Association ID the association number + * in the internal association array, which is filled by the ntpq_get_assocs + * function. + * + **************************************************************************** + * Parameters: + * associd int requested associaton ID + * + * Returns: + * int the number of the association array element that is + * representing the given association ID + * - OR - + * -1 if a failure occured or no matching association + * ID has been found + ****************************************************************************/ + +int ntpq_get_assoc_number ( associd_t associd ) +{ + int i; + + for (i=0;i<numassoc;i++) { + if (assoc_cache[i].assid == associd) + return i; + } + + return -1; + +} + + +/***************************************************************************** + * + * ntpq_read_assoc_peervars + * + * This function reads the peervars variable-set of a specified association + * from a NTP host and writes it to the result buffer specified, honoring + * the maxsize limit. + * + * It returns the number of bytes written or 0 when the variable-set is + * empty or failed to read. + * + **************************************************************************** + * Parameters: + * associd int requested associaton ID + * resultbuf char* character buffer where the variable set + * should be stored + * maxsize int the maximum number of bytes that can be + * written to resultbuf + * + * Returns: + * int number of chars that have been copied to + * resultbuf + * - OR - + * 0 (zero) if an error occured + ****************************************************************************/ + +int +ntpq_read_assoc_peervars( + associd_t associd, + char * resultbuf, + int maxsize + ) +{ + const char * datap; + int res; + int dsize; + u_short rstatus; + + res = doquery(CTL_OP_READVAR, associd, 0, 0, NULL, &rstatus, + &dsize, &datap); + if (res != 0) + return 0; + if (dsize <= 0) { + if (numhosts > 1) + fprintf(stderr, "server=%s ", currenthost); + fprintf(stderr, + "***No information returned for association %d\n", + associd); + + return 0; + } + if (dsize > maxsize) + dsize = maxsize; + memcpy(resultbuf, datap, dsize); + + return dsize; +} + + + + +/***************************************************************************** + * + * ntpq_read_sysvars + * + * This function reads the sysvars variable-set from a NTP host and writes it + * to the result buffer specified, honoring the maxsize limit. + * + * It returns the number of bytes written or 0 when the variable-set is empty + * or could not be read. + * + **************************************************************************** + * Parameters: + * resultbuf char* character buffer where the variable set + * should be stored + * maxsize int the maximum number of bytes that can be + * written to resultbuf + * + * Returns: + * int number of chars that have been copied to + * resultbuf + * - OR - + * 0 (zero) if an error occured + ****************************************************************************/ +size_t +ntpq_read_sysvars( + char * resultbuf, + size_t maxsize + ) +{ + const char * datap; + int res; + int i_dsize; + size_t dsize; + u_short rstatus; + + res = doquery(CTL_OP_READVAR, 0, 0, 0, NULL, &rstatus, + &i_dsize, &datap); + + if (res != 0) + return 0; + + if (i_dsize == 0) { + if (numhosts > 1) + fprintf(stderr, "server=%s ", currenthost); + fprintf(stderr, "***No sysvar information returned\n"); + + return 0; + } else { + dsize = max(0, i_dsize); + dsize = min(dsize, maxsize); + memcpy(resultbuf, datap, dsize); + } + + return dsize; +} + + +/***************************************************************************** + * ntpq_get_assoc_allvars + * + * With this function all association variables for the specified association + * ID can be requested from a NTP host. They are stored internally and can be + * read by using the ntpq_get_peervar or ntpq_get_clockvar functions. + * + * Basically this is only a combination of the ntpq_get_assoc_peervars and + * ntpq_get_assoc_clockvars functions. + * + * It returns 1 if both variable-sets (peervars and clockvars) were + * received successfully. If one variable-set or both of them weren't + * received, + * + **************************************************************************** + * Parameters: + * associd int requested associaton ID + * + * Returns: + * int nonzero if at least one variable set could be read + * - OR - + * 0 (zero) if an error occured and both variable sets + * could not be read + ****************************************************************************/ + int ntpq_get_assoc_allvars( associd_t associd ) +{ + return ntpq_get_assoc_peervars ( associd ) & + ntpq_get_assoc_clockvars( associd ); +} + + + + +/***************************************************************************** + * + * ntpq_get_sysvars + * + * The system variables of a NTP host can be requested by using this function + * and afterwards using ntpq_get_sysvar to read the single variable values. + * + **************************************************************************** + * Parameters: + * - none - + * + * Returns: + * int nonzero if the variable set could be read + * - OR - + * 0 (zero) if an error occured and the sysvars + * could not be read + ****************************************************************************/ +int +ntpq_get_sysvars(void) +{ + sysvarlen = ntpq_read_sysvars(sysvars, sizeof(sysvars)); + if (sysvarlen <= 0) + return 0; + else + return 1; +} + + +/***************************************************************************** + * + * ntp_get_peervar + * + * This function uses the variable-set which was read by using + * ntp_get_peervars and searches for a variable specified with varname. If + * such a variable exists, it writes its value into + * varvalue (maxlen specifies the size of this target buffer). + * + **************************************************************************** + * Parameters: + * varname char* requested variable name + * varvalue char* the buffer where the value should go into + * maxlen int maximum number of bytes that can be copied to + * varvalue + * + * Returns: + * int number of bytes copied to varvalue + * - OR - + * 0 (zero) if an error occured or the variable could + * not be found + ****************************************************************************/ +int ntpq_get_peervar( const char *varname, char *varvalue, int maxlen) +{ + return ( ntpq_getvar(peervars,peervarlen,varname,varvalue,maxlen) ); +} + + + +/***************************************************************************** + * + * ntpq_get_assoc_peervars + * + * This function requests the peer variables of the specified association + * from a NTP host. In order to access the variable values, the function + * ntpq_get_peervar must be used. + * + **************************************************************************** + * Parameters: + * associd int requested associaton ID + * + * Returns: + * int 1 (one) if the peervars have been read + * - OR - + * 0 (zero) if an error occured and the variable set + * could not be read + ****************************************************************************/ +int +ntpq_get_assoc_peervars( + associd_t associd + ) +{ + peervarlen = ntpq_read_assoc_peervars(associd, peervars, + sizeof(peervars)); + if (peervarlen <= 0) { + peervar_assoc = 0; + + return 0; + } + peervar_assoc = associd; + + return 1; +} + + +/***************************************************************************** + * + * ntp_read_assoc_clockvars + * + * This function reads the clockvars variable-set of a specified association + * from a NTP host and writes it to the result buffer specified, honoring + * the maxsize limit. + * + * It returns the number of bytes written or 0 when the variable-set is + * empty or failed to read. + * + **************************************************************************** + * Parameters: + * associd int requested associaton ID + * resultbuf char* character buffer where the variable set + * should be stored + * maxsize int the maximum number of bytes that can be + * written to resultbuf + * + * Returns: + * int number of chars that have been copied to + * resultbuf + * - OR - + * 0 (zero) if an error occured + ****************************************************************************/ + +int +ntpq_read_assoc_clockvars( + associd_t associd, + char * resultbuf, + int maxsize + ) +{ + const char *datap; + int res; + int dsize; + u_short rstatus; + + res = ntpq_doquerylist(ntpq_varlist, CTL_OP_READCLOCK, associd, + 0, &rstatus, &dsize, &datap); + if (res != 0) + return 0; + + if (dsize == 0) { + if (numhosts > 1) /* no information returned from server */ + return 0; + } else { + if (dsize > maxsize) + dsize = maxsize; + memcpy(resultbuf, datap, dsize); + } + + return dsize; +} + + + +/***************************************************************************** + * + * ntpq_get_assoc_clocktype + * + * This function returns a clocktype value for a given association number + * (not ID!): + * + * NTP_CLOCKTYPE_UNKNOWN Unknown clock type + * NTP_CLOCKTYPE_BROADCAST Broadcast server + * NTP_CLOCKTYPE_LOCAL Local clock + * NTP_CLOCKTYPE_UNICAST Unicast server + * NTP_CLOCKTYPE_MULTICAST Multicast server + * + ****************************************************************************/ +int +ntpq_get_assoc_clocktype( + int assoc_index + ) +{ + associd_t associd; + int i; + int rc; + sockaddr_u dum_store; + char dstadr[LENHOSTNAME]; + char resultbuf[NTPQ_BUFLEN]; + + if (assoc_index < 0 || assoc_index >= numassoc) + return -1; + + associd = assoc_cache[assoc_index].assid; + if (associd == peervar_assoc) { + rc = ntpq_get_peervar("dstadr", dstadr, sizeof(dstadr)); + } else { + i = ntpq_read_assoc_peervars(associd, resultbuf, + sizeof(resultbuf)); + if (i <= 0) + return -1; + rc = ntpq_getvar(resultbuf, i, "dstadr", dstadr, + sizeof(dstadr)); + } + + if (0 != rc && decodenetnum(dstadr, &dum_store)) + return ntpq_decodeaddrtype(&dum_store); + + return -1; +} + + + +/***************************************************************************** + * + * ntpq_get_assoc_clockvars + * + * With this function the clock variables of the specified association are + * requested from a NTP host. This makes only sense for associations with + * the type 'l' (Local Clock) and you should check this with + * ntpq_get_assoc_clocktype for each association, before you use this function + * on it. + * + **************************************************************************** + * Parameters: + * associd int requested associaton ID + * + * Returns: + * int 1 (one) if the clockvars have been read + * - OR - + * 0 (zero) if an error occured and the variable set + * could not be read + ****************************************************************************/ +int ntpq_get_assoc_clockvars( associd_t associd ) +{ + if (NTP_CLOCKTYPE_LOCAL != ntpq_get_assoc_clocktype( + ntpq_get_assoc_number(associd))) + return 0; + clockvarlen = ntpq_read_assoc_clockvars( associd, clockvars, + sizeof(clockvars) ); + if ( clockvarlen <= 0 ) { + clockvar_assoc = 0; + return 0; + } else { + clockvar_assoc = associd; + return 1; + } +} + + |