From: Dave Hart Date: Fri, 30 Apr 2010 17:24:16 +0000 (+0000) Subject: [Bug 1542] ntpd mrulist response may have incorrect last.older. X-Git-Tag: NTP_4_2_7P30~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=82b2c05f8f1d2be67087e97c16e4a0f629700e62;p=thirdparty%2Fntp.git [Bug 1542] ntpd mrulist response may have incorrect last.older. [Bug 1543] ntpq mrulist must refresh nonce when retrying. [Bug 1544] ntpq mrulist sscanf timestamp format mismatch on 64-bit. Windows compiling hints/winnt.html update from Sunil Tej S. bk: 4bdb1240O080WSqNRsJybnkF_5GViA --- diff --git a/ChangeLog b/ChangeLog index 5631c0992..242ff8b88 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,13 @@ +* [Bug 1542] ntpd mrulist response may have incorrect last.older. +* [Bug 1543] ntpq mrulist must refresh nonce when retrying. +* [Bug 1544] ntpq mrulist sscanf timestamp format mismatch on 64-bit. +* Windows compiling hints/winnt.html update from Sunil Tej S. (4.2.7p27) 2010/04/27 Released by Harlan Stenn (4.2.7p26) 2010/04/24 Released by Harlan Stenn -* [Bug 1465] Make sure time from TS2100 is not invalid (backport from -dev). -* [Bug 1528] Fix EDITLINE_LIBS link order for ntpq and ntpdc. +* Include (4.2.6p2-RC2) [Bug 1465] Make sure time from TS2100 is not + invalid (backport from -dev). +* Include (4.2.6p2-RC2) [Bug 1528] Fix EDITLINE_LIBS link order for ntpq + and ntpdc. * [Bug 1531] Require nonce with mrulist requests. * [Bug 1532] Remove ntpd support for ntpdc's monlist in favor of ntpq's mrulist. diff --git a/html/hints/winnt.html b/html/hints/winnt.html index 49d9cbc22..a2d277fa9 100644 --- a/html/hints/winnt.html +++ b/html/hints/winnt.html @@ -45,21 +45,23 @@

Compiling Requirements

    -
  • Windows NT 4.0 Windows 2000, Windows XP, or Windows.NET Server 2003 -
  • Microsoft Visual C++ 6.0. NOTEVC++ 7.0 (aka .NET) is not yet supported - but will probably work fine. +
  • Windows NT 4.0 Windows 2000, Windows XP,Windows Vista or Windows.NET Server 2003 +
  • Microsoft Visual C++ 2008 EE or Visual C++ 2010 EE
  • Some way of uncompressing and untarring the gzipped tar file.
  • OpenSSL must be built on the box before building NTP. Additional steps would be required to not use OpenSSL. -
- Compiling Instructions +
  • Microsoft Visual C++ redistributables + Compiling Instructions
      -
    1. Unpack and build OpenSSL according to the OpenSSL instructions for building on Windows. Currently the NTP build requires OpenSSL 0.9.7b as it looks for the path to that build for the include and libeay32.lib files. If you have a different version you will need to adjust both the preprocessor path and the link path to point to the correct locations of the include files and the lib file respectively. -
    2. Unpack the NTP-4.x.tar.gz using utilities such as WinZip. -
    3. Open the .\ports\winnt\ntp.dsw Visual C workspace -
    4. Batch build all projects -
    5. The built binaries can be found in the port\winnt\bin\Release subdirectory -
    6. In addition you will need to install the OpenSSL libeay32.dll +
    7. Install Micosoft Visual C++ redistributables +
    8. Install OpenSSL full installer for Windows. Add the following to your system environment variables in the control panel (adjusting paths as appropriate to point to the directory containing only an openssl subdirectory, for OPENSSL_INC, and to the directory containing openssl .lib files for OPENSSL_LIB: +
      • OPENSSL_INC=C:\OpenSSL\include +
      • OPENSSL_LIB=C:\OpenSSL\lib
      +
    9. Unpack the NTP-4.x.tar.gz using utilities such as WinZip or WinRar. +
    10. Run Microsoft Visual C++ 2008 EE. On Windows Vista and later, Run as Administrator. +
    11. Open the ports\winnt\vs2008\ntp.sln solution file +
    12. Batch build all projects (Build menu, Batch Build..., select all, build). +
    13. The built binaries can be found in the ports\winnt\v2008\bin\ directory.
    14. If you are shipping binaries in a kit it is strongly recommended that you ship this file (winnt.html) along with the binaries.

    Configuration File

    diff --git a/ntpd/ntp_control.c b/ntpd/ntp_control.c index fec962525..c742c97bd 100644 --- a/ntpd/ntp_control.c +++ b/ntpd/ntp_control.c @@ -3128,8 +3128,11 @@ static void read_mru_list( mon = mon->hash_next) if (ADDR_PORT_EQ(&mon->rmtadr, &addr[i])) break; - if (mon != NULL && L_ISEQU(&mon->last, &last[i])) - break; + if (mon != NULL) { + if (L_ISEQU(&mon->last, &last[i])) + break; + mon = NULL; + } } /* If a starting point was provided... */ diff --git a/ntpq/ntpq-subs.c b/ntpq/ntpq-subs.c index 21876635f..9777f8cb1 100644 --- a/ntpq/ntpq-subs.c +++ b/ntpq/ntpq-subs.c @@ -304,6 +304,7 @@ typedef struct var_display_collection_tag { */ static mru * add_mru(mru *); static int collect_mru_list(const char *, l_fp *); +static int fetch_nonce(char *, size_t); static int qcmp_mru_avgint(const void *, const void *); static int qcmp_mru_r_avgint(const void *, const void *); static int qcmp_mru_addr(const void *, const void *); @@ -2176,6 +2177,52 @@ config_from_file ( } +static int +fetch_nonce( + char * nonce, + size_t cb_nonce + ) +{ + const char nonce_eq[] = "nonce="; + int qres; + u_short rstatus; + int rsize; + const char * rdata; + int chars; + + /* + * Retrieve a nonce specific to this client to demonstrate to + * ntpd that we're capable of receiving responses to our source + * IP address, and thereby unlikely to be forging the source. + */ + qres = doquery(CTL_OP_REQ_NONCE, 0, 0, 0, NULL, &rstatus, + &rsize, &rdata); + if (qres) { + fprintf(stderr, "nonce request failed\n"); + return FALSE; + } + + if (rsize <= sizeof(nonce_eq) - 1 || + strncmp(rdata, nonce_eq, sizeof(nonce_eq) - 1)) { + fprintf(stderr, "unexpected nonce response format: %.*s\n", + rsize, rdata); + return FALSE; + } + chars = rsize - (sizeof(nonce_eq) - 1); + if (chars >= (int)cb_nonce) + return FALSE; + memcpy(nonce, rdata + sizeof(nonce_eq) - 1, chars); + nonce[chars] = '\0'; + while (chars > 0 && + ('\r' == nonce[chars - 1] || '\n' == nonce[chars - 1])) { + chars--; + nonce[chars] = '\0'; + } + + return TRUE; +} + + /* * add_mru Add and entry to mru list, hash table, and allocate * and return a replacement. @@ -2190,13 +2237,6 @@ add_mru( mru *mon; mru *unlinked; - if (debug) - fprintf(stderr, - "add_mru %08x.%08x c %d m %d v %d rest %x first %08x.%08x %s\n", - add->last.l_ui, add->last.l_uf, add->count, - (int)add->mode, (int)add->ver, (u_int)add->rs, - add->first.l_ui, add->first.l_uf, - sptoa(&add->addr)); hash = NTP_HASH_ADDR(&add->addr); /* see if we have it among previously received entries */ @@ -2217,19 +2257,25 @@ add_mru( UNLINK_SLIST(unlinked, hash_table[hash], mon, hlink, mru); NTP_INSIST(unlinked == mon); if (debug) - fprintf(stderr, - "add_mru duplicate removed %s %08x.%08x -> %08x.%08x\n", - sptoa(&mon->addr), mon->last.l_ui, - mon->last.l_uf, add->last.l_ui, - add->last.l_uf); + fprintf(stderr, "(updated from %08x.%08x) ", + mon->last.l_ui, mon->last.l_uf); } LINK_DLIST(mru_list, add, mlink); LINK_SLIST(hash_table[hash], add, hlink); + if (debug) + fprintf(stderr, + "add_mru %08x.%08x c %d m %d v %d rest %x first %08x.%08x %s\n", + add->last.l_ui, add->last.l_uf, add->count, + (int)add->mode, (int)add->ver, (u_int)add->rs, + add->first.l_ui, add->first.l_uf, + sptoa(&add->addr)); + /* if we didn't update an existing entry, alloc replacement */ if (NULL == mon) { mon = emalloc(sizeof(*mon)); mru_count++; } memset(mon, 0, sizeof(*mon)); + return mon; } @@ -2252,11 +2298,10 @@ collect_mru_list( l_fp * pnow ) { + const u_int sleep_msecs = 30; static int ntpd_row_limit = MRU_ROW_LIMIT; int c_mru_l_rc; /* this function's return code */ u_char got; /* MRU_GOT_* bits */ - const char ts_fmt[] = "0x%08x.%08x"; - const char nonce_eq[] = "nonce="; size_t cb; mru *mon; mru *head; @@ -2285,37 +2330,20 @@ collect_mru_list( int have_now; int have_addr_older; int have_last_older; + u_int restarted_count; + u_int nonce_uses; u_short hash; mru *unlinked; - /* - * Retrieve a nonce specific to this client to demonstrate to - * ntpd that we're capable of receiving responses to our source - * IP address, and thereby unlikely to be forging the source. - */ - qres = doquery(CTL_OP_REQ_NONCE, 0, 0, 0, NULL, &rstatus, - &rsize, &rdata); - if (qres) { - fprintf(stderr, "nonce request failed\n"); - return FALSE; - } - - if (strncmp(rdata, nonce_eq, sizeof(nonce_eq) - 1)) { - fprintf(stderr, "unexpected nonce response format: %.*s\n", - rsize, rdata); + if (!fetch_nonce(nonce, sizeof(nonce))) return FALSE; - } - strncpy(nonce, rdata + sizeof(nonce_eq) - 1, sizeof(nonce)); - chars = strlen(nonce); - while (chars > 0 && - ('\r' == nonce[chars - 1] || '\n' == nonce[chars - 1])) { - chars--; - nonce[chars] = '\0'; - } + nonce_uses = 0; + restarted_count = 0; mru_count = 0; INIT_DLIST(mru_list, mlink); cb = NTP_HASH_SIZE * sizeof(*hash_table); + NTP_INSIST(NULL == hash_table); hash_table = emalloc(cb); memset(hash_table, 0, cb); @@ -2333,11 +2361,12 @@ collect_mru_list( limit = min(3 * MAXFRAGS, ntpd_row_limit); snprintf(req_buf, sizeof(req_buf), "nonce=%s, limit=%d%s", nonce, limit, parms); + nonce_uses++; while (TRUE) { if (debug) fprintf(stderr, "READ_MRU parms: %s\n", req_buf); - + qres = doqueryex(CTL_OP_READ_MRU, 0, 0, strlen(req_buf), req_buf, &rstatus, &rsize, &rdata, TRUE); @@ -2347,31 +2376,61 @@ collect_mru_list( * toss them from our list and try again. */ if (debug) - printf("no overlap between %d prior entries and server MRU list\n", - ri); + fprintf(stderr, + "no overlap between %d prior entries and server MRU list\n", + ri); while (ri--) { recent = HEAD_DLIST(mru_list, mlink); NTP_INSIST(recent != NULL); if (debug) - printf("tossing prior entry %s to resync\n", - sptoa(&recent->addr)); + fprintf(stderr, + "tossing prior entry %s to resync\n", + sptoa(&recent->addr)); UNLINK_DLIST(recent, mlink); hash = NTP_HASH_ADDR(&recent->addr); UNLINK_SLIST(unlinked, hash_table[hash], recent, hlink, mru); NTP_INSIST(unlinked == recent); free(recent); + mru_count--; + } + if (NULL == HEAD_DLIST(mru_list, mlink)) { + restarted_count++; + if (restarted_count > 8) { + fprintf(stderr, + "Giving up after 8 restarts from the beginning.\n" + "With high-traffic NTP servers, this can occur if the\n" + "MRU list is limited to less than about 16 seconds' of\n" + "entries. See the 'mru' ntp.conf directive to adjust.\n"); + goto cleanup_return; + } + if (debug) + fprintf(stderr, + "---> Restarting from the beginning, retry #%u\n", + restarted_count); } + } else if (CERR_UNKNOWNVAR == qres) { + fprintf(stderr, + "CERR_UNKNOWNVAR from ntpd but no priors given.\n"); + goto cleanup_return; } else if (CERR_BADVALUE == qres) { /* ntpd has lower cap on row limit */ ntpd_row_limit--; limit = min(limit, ntpd_row_limit); + if (debug) + fprintf(stderr, + "Row limit reduced to %d following CERR_BADVALUE.\n", + limit); } else if (ERR_INCOMPLETE == qres) { /* * Reduce the number of rows to minimize effect * of single lost packets. */ limit = max(2, limit / 2); + if (debug) + fprintf(stderr, + "Row limit reduced to %d following incomplete response.\n", + limit); } else if (qres) { show_error_msg(qres, 0); goto cleanup_return; @@ -2392,7 +2451,8 @@ collect_mru_list( have_last_older = FALSE; while (!qres && nextvar(&rsize, &rdata, &tag, &val)) { if (debug > 1) - fprintf(stderr, "nextvar gave: %s = %s\n", tag, val); + fprintf(stderr, "nextvar gave: %s = %s\n", + tag, val); switch(tag[0]) { case 'a': @@ -2443,9 +2503,9 @@ collect_mru_list( case 'l': if (!strcmp(tag, "last.older")) { - if (2 != sscanf(val, ts_fmt, - &last_older.l_ui, - &last_older.l_uf)) { + if ('0' != val[0] || + 'x' != val[1] || + !hextolfp(val + 2, &last_older)) { fprintf(stderr, "last.older %s garbled\n", val); @@ -2467,9 +2527,9 @@ collect_mru_list( } head = HEAD_DLIST(mru_list, mlink); if (NULL != head) { - if (2 != sscanf(val, ts_fmt, - &newest.l_ui, - &newest.l_uf) || + if ('0' != val[0] || + 'x' != val[1] || + !hextolfp(val + 2, &newest) || !L_ISEQU(&newest, &head->last)) { fprintf(stderr, @@ -2481,11 +2541,10 @@ collect_mru_list( } } list_complete = TRUE; - } else if (1 != sscanf(tag, "last.%d", &si) - || si != ci || - 2 != sscanf(val, ts_fmt, - &mon->last.l_ui, - &mon->last.l_uf)) + } else if (1 != sscanf(tag, "last.%d", &si) || + si != ci || '0' != val[0] || + 'x' != val[1] || + !hextolfp(val + 2, &mon->last)) goto nomatch; else MGOT(MRU_GOT_LAST); @@ -2493,23 +2552,22 @@ collect_mru_list( case 'f': if (1 != sscanf(tag, "first.%d", &si) || - si != ci || - 2 != sscanf(val, ts_fmt, - &mon->first.l_ui, - &mon->first.l_uf)) + si != ci || '0' != val[0] || + 'x' != val[1] || + !hextolfp(val + 2, &mon->first)) goto nomatch; MGOT(MRU_GOT_FIRST); break; case 'n': if (!strcmp(tag, "nonce")) { - strncpy(nonce, val, - sizeof(nonce)); + strncpy(nonce, val, sizeof(nonce)); + nonce_uses = 0; break; /* case */ } else if (strcmp(tag, "now") || - 2 != sscanf(val, ts_fmt, - &pnow->l_ui, - &pnow->l_uf)) + '0' != val[0] || + 'x' != val[1] || + !hextolfp(val + 2, pnow)) goto nomatch; have_now = TRUE; break; @@ -2558,12 +2616,13 @@ collect_mru_list( * up with other duties. */ #ifdef SYS_WINNT - Sleep(300); /* msec */ + Sleep(sleep_msecs); #elif !defined(HAVE_NANOSLEEP) - sleep(1); + sleep((sleep_msecs / 1000) + 1); #else { - struct timespec interv = { 0, 300 * 1000 }; + struct timespec interv = { 0, + 1000 * sleep_msecs }; nanosleep(&interv, NULL); } #endif @@ -2587,6 +2646,13 @@ collect_mru_list( snprintf(req, REQ_ROOM, "nonce=%s, limit=%d%s", nonce, limit, parms); req += strlen(req); + nonce_uses++; + if (nonce_uses >= 4) { + if (!fetch_nonce(nonce, sizeof(nonce))) + goto cleanup_return; + nonce_uses = 0; + } + for (ri = 0, recent = HEAD_DLIST(mru_list, mlink); recent != NULL; @@ -2602,12 +2668,16 @@ collect_mru_list( memcpy(req, buf, chars + 1); req += chars; } - NTP_INSIST(ri > 0 || NULL == recent); } c_mru_l_rc = TRUE; + goto retain_hash_table; cleanup_return: + free(hash_table); + hash_table = NULL; + +retain_hash_table: if (mon != NULL) free(mon); @@ -2888,6 +2958,14 @@ mrulist( REV_ITER_DLIST_END() } + if (ppentry - sorted != (int)mru_count) { + fprintf(stderr, + "mru_count %u should match MRU list depth %d.\n", + mru_count, ppentry - sorted); + free(sorted); + goto cleanup_return; + } + /* re-sort sorted[] if not default or reverse default */ if (MRUSORT_R_DEF < order) qsort(sorted, mru_count, sizeof(sorted[0]),