From: Dave Hart Date: Mon, 31 Oct 2011 03:52:23 +0000 (+0000) Subject: Directly limit the number of datagrams in a mrulist response, rather X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a450faed64a3553585bd32ffe2bdaafc871562ae;p=thirdparty%2Fntp.git Directly limit the number of datagrams in a mrulist response, rather than limiting the number of entries returned to indirectly limit the datagram count. bk: 4eae1b77cUUXbsW3PsM7mikdHghaPQ --- diff --git a/ChangeLog b/ChangeLog index 308b9044ff..b1c8cdc37f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +* Directly limit the number of datagrams in a mrulist response, rather + than limiting the number of entries returned to indirectly limit the + datagram count. (4.2.7p229) 2011/10/26 Released by Harlan Stenn * [Bug 1995] fix wrong use of ZERO() macro in 'ntp_calendar.c' (4.2.7p228) 2011/10/23 Released by Harlan Stenn diff --git a/include/ntp.h b/include/ntp.h index 3f67eb1e8d..71181a8f60 100644 --- a/include/ntp.h +++ b/include/ntp.h @@ -880,4 +880,6 @@ struct endpoint { /* ntpq -c mrulist rows per request limit in ntpd */ #define MRU_ROW_LIMIT 256 +/* similar datagrams per response limit for ntpd */ +#define MRU_FRAGS_LIMIT 128 #endif /* NTP_H */ diff --git a/libntp/ntp_random.c b/libntp/ntp_random.c index 28deea467f..4d133b6d0f 100644 --- a/libntp/ntp_random.c +++ b/libntp/ntp_random.c @@ -45,7 +45,7 @@ static char sccsid[] = "@(#)random.c 8.2 (Berkeley) 5/19/95"; #endif #include -#include +#include #include #include @@ -261,19 +261,22 @@ ntp_srandom( unsigned long x ) { - register long i; + long i; - if (rand_type == TYPE_0) + if (rand_type == TYPE_0) { state[0] = x; - else { + } else { state[0] = x; for (i = 1; i < rand_deg; i++) state[i] = good_rand(state[i - 1]); fptr = &state[rand_sep]; rptr = &state[0]; for (i = 0; i < 10 * rand_deg; i++) - (void)ntp_random(); + x = ntp_random(); } + + /* seed the likely faster (and poorer) rand() as well */ + srand((u_int)x); } /* diff --git a/ntpd/ntp_control.c b/ntpd/ntp_control.c index 7ace0675be..9594b226d2 100644 --- a/ntpd/ntp_control.c +++ b/ntpd/ntp_control.c @@ -764,7 +764,8 @@ static struct ntp_control rpkt; static u_char res_version; static u_char res_opcode; static associd_t res_associd; -static int res_offset; +static u_short res_frags; /* datagrams in this response */ +static int res_offset; /* offset of payload in response */ static u_char * datapt; static u_char * dataend; static int datalinelen; @@ -778,7 +779,7 @@ static keyid_t res_keyid; #define MAXDATALINELEN (72) -static u_char res_async; /* set to 1 if this is async trap response */ +static u_char res_async; /* sending async trap response? */ /* * Pointers for saving state when decoding request packets @@ -1035,14 +1036,15 @@ process_control( rpkt.sequence = pkt->sequence; rpkt.associd = pkt->associd; rpkt.status = 0; + res_frags = 1; res_offset = 0; res_associd = htons(pkt->associd); - res_async = 0; - res_authenticate = 0; + res_async = FALSE; + res_authenticate = FALSE; res_keyid = 0; - res_authokay = 0; + res_authokay = FALSE; req_count = (int)ntohs(pkt->count); - datanotbinflag = 0; + datanotbinflag = FALSE; datalinelen = 0; datapt = rpkt.u.data; dataend = &rpkt.u.data[CTL_MAX_DATA_LEN]; @@ -1070,7 +1072,7 @@ process_control( if ((rbufp->recv_length & 3) == 0 && maclen >= MIN_MAC_LEN && maclen <= MAX_MAC_LEN && sys_authenticate) { - res_authenticate = 1; + res_authenticate = TRUE; pkid = (void *)((char *)pkt + properlen); res_keyid = ntohl(*pkid); DPRINTF(3, ("recv_len %d, properlen %d, wants auth with keyid %08x, MAC length=%d\n", @@ -1082,7 +1084,7 @@ process_control( else if (authdecrypt(res_keyid, (u_int32 *)pkt, rbufp->recv_length - maclen, maclen)) { - res_authokay = 1; + res_authokay = TRUE; DPRINTF(3, ("authenticated okay\n")); } else { res_keyid = 0; @@ -1266,9 +1268,10 @@ ctl_flushpkt( (u_int32 *)&rpkt, totlen); sendpkt(rmt_addr, lcl_inter, -5, (struct pkt *)&rpkt, totlen + maclen); - } else + } else { sendpkt(rmt_addr, lcl_inter, -6, (struct pkt *)&rpkt, sendlen); + } if (more) numctlfrags++; else @@ -1278,6 +1281,7 @@ ctl_flushpkt( /* * Set us up for another go around. */ + res_frags++; res_offset += dlen; datapt = rpkt.u.data; } @@ -1298,7 +1302,7 @@ ctl_putdata( overhead = 0; if (!bin) { - datanotbinflag = 1; + datanotbinflag = TRUE; overhead = 3; if (datapt != rpkt.u.data) { *datapt++ = ','; @@ -3414,17 +3418,18 @@ send_mru_entry( * and ifstats responses, the first and last rows are spiced with * randomly-generated tag names with correct .# index. * Make it three characters knowing that none of the currently-used - * tags have that length, avoiding the need to test for tag collision. + * subscripted tags have that length, avoiding the need to test for + * tag collision. */ static void send_random_tag_value( int indx ) { - u_long noise; + int noise; char buf[32]; - noise = ntp_random(); + noise = rand(); buf[0] = 'a' + noise % 26; noise >>= 5; buf[1] = 'a' + noise % 26; @@ -3472,14 +3477,18 @@ send_random_tag_value( * nonce= Regurgitated nonce retrieved by the client * previously using CTL_OP_REQ_NONCE, demonstrating * ability to receive traffic sent to its address. - * limit= Limit on MRU entries returned. This is the sole - * required input parameter. [1...256] + * frags= Limit on datagrams (fragments) in response. Used + * by newer ntpq versions instead of limit= when + * retrieving multiple entries. + * limit= Limit on MRU entries returned. One of frags= or + * limit= must be provided. * limit=1 is a special case: Instead of fetching * beginning with the supplied starting point's * newer neighbor, fetch the supplied entry, and * in that case the #.last timestamp can be zero. * This enables fetching a single entry by IP - * address. + * address. When limit is not one and frags= is + * provided, the fragment limit controls. * mincount= (decimal) Return entries with count >= mincount. * laddr= Return entries associated with the server's IP * address given. No port specification is needed, @@ -3554,6 +3563,7 @@ static void read_mru_list( ) { const char nonce_text[] = "nonce"; + const char frags_text[] = "frags"; const char limit_text[] = "limit"; const char mincount_text[] = "mincount"; const char resall_text[] = "resall"; @@ -3562,6 +3572,7 @@ static void read_mru_list( const char laddr_text[] = "laddr"; const char resaxx_fmt[] = "0x%hx"; u_int limit; + u_short frags; u_short resall; u_short resany; int mincount; @@ -3592,6 +3603,7 @@ static void read_mru_list( */ in_parms = NULL; set_var(&in_parms, nonce_text, sizeof(nonce_text), 0); + set_var(&in_parms, frags_text, sizeof(frags_text), 0); set_var(&in_parms, limit_text, sizeof(limit_text), 0); set_var(&in_parms, mincount_text, sizeof(mincount_text), 0); set_var(&in_parms, resall_text, sizeof(resall_text), 0); @@ -3607,6 +3619,7 @@ static void read_mru_list( /* decode input parms */ pnonce = NULL; + frags = 0; limit = 0; mincount = 0; resall = 0; @@ -3624,19 +3637,21 @@ static void read_mru_list( if (NULL != pnonce) free(pnonce); pnonce = estrdup(val); - } else if (!strcmp(limit_text, v->text)) + } else if (!strcmp(frags_text, v->text)) { + sscanf(val, "%hu", &frags); + } else if (!strcmp(limit_text, v->text)) { sscanf(val, "%u", &limit); - else if (!strcmp(mincount_text, v->text)) { + } else if (!strcmp(mincount_text, v->text)) { if (1 != sscanf(val, "%d", &mincount) || mincount < 0) mincount = 0; - } else if (!strcmp(resall_text, v->text)) + } else if (!strcmp(resall_text, v->text)) { sscanf(val, resaxx_fmt, &resall); - else if (!strcmp(resany_text, v->text)) + } else if (!strcmp(resany_text, v->text)) { sscanf(val, resaxx_fmt, &resany); - else if (!strcmp(maxlstint_text, v->text)) + } else if (!strcmp(maxlstint_text, v->text)) { sscanf(val, "%u", &maxlstint); - else if (!strcmp(laddr_text, v->text)) { + } else if (!strcmp(laddr_text, v->text)) { if (decodenetnum(val, &laddr)) lcladr = getinterface(&laddr, 0); } else if (1 == sscanf(v->text, last_fmt, &i) && @@ -3668,11 +3683,20 @@ static void read_mru_list( if (!nonce_valid) return; - if (!(0 < limit && limit <= MRU_ROW_LIMIT)) { + if ((0 == frags && !(0 < limit && limit <= MRU_ROW_LIMIT)) || + frags > MRU_FRAGS_LIMIT) { ctl_error(CERR_BADVALUE); return; } + /* + * If either frags or limit is not given, use the max. + */ + if (0 != frags && 0 == limit) + limit = UINT_MAX; + else if (0 != limit && 0 == frags) + frags = MRU_FRAGS_LIMIT; + /* * Find the starting point if one was provided. */ @@ -3711,18 +3735,19 @@ static void read_mru_list( */ if (limit > 1) mon = PREV_DLIST(mon_mru_list, mon, mru); - } else /* start with the oldest */ + } else { /* start with the oldest */ mon = TAIL_DLIST(mon_mru_list, mru); + } /* - * send up to limit= entries + * send up to limit= entries in up to frags= datagrams */ get_systime(&now); generate_nonce(rbufp, buf, sizeof(buf)); ctl_putunqstr("nonce", buf, strlen(buf)); prior_mon = NULL; for (count = 0; - count < limit && mon != NULL; + mon != NULL && res_frags < frags && count < limit; mon = PREV_DLIST(mon_mru_list, mon, mru)) { if (mon->count < mincount) @@ -4381,8 +4406,8 @@ report_event( */ res_opcode = CTL_OP_ASYNCMSG; res_offset = 0; - res_async = 1; - res_authenticate = 0; + res_async = TRUE; + res_authenticate = FALSE; datapt = rpkt.u.data; dataend = &rpkt.u.data[CTL_MAX_DATA_LEN]; if (!(err & PEER_EVENT)) { diff --git a/ntpq/ntpq-subs.c b/ntpq/ntpq-subs.c index 6a577c1a2f..2605d12c83 100644 --- a/ntpq/ntpq-subs.c +++ b/ntpq/ntpq-subs.c @@ -2249,6 +2249,8 @@ collect_mru_list( int rsize; const char *rdata; int limit; + int frags; + int cap_frags; char *tag; char *val; int si; /* server index in response */ @@ -2280,6 +2282,7 @@ collect_mru_list( c_mru_l_rc = FALSE; list_complete = FALSE; have_now = FALSE; + cap_frags = TRUE; got = 0; ri = 0; cb = sizeof(*mon); @@ -2294,8 +2297,9 @@ collect_mru_list( next_report = time(NULL) + MRU_REPORT_SECS; limit = min(3 * MAXFRAGS, ntpd_row_limit); - snprintf(req_buf, sizeof(req_buf), "nonce=%s, limit=%d%s", - nonce, limit, parms); + frags = MAXFRAGS; + snprintf(req_buf, sizeof(req_buf), "nonce=%s, frags=%d%s", + nonce, frags, parms); nonce_uses++; while (TRUE) { @@ -2349,24 +2353,39 @@ collect_mru_list( "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); + if (cap_frags) { + cap_frags = FALSE; + if (debug) + fprintf(stderr, + "Reverted to row limit from fragments limit.\n"); + } else { + /* 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 || ERR_TIMEOUT == qres) { /* - * Reduce the number of rows to minimize effect - * of single lost packets. + * Reduce the number of rows/frags requested by + * half to recover from lost response fragments. */ - limit = max(2, limit / 2); - if (debug) - fprintf(stderr, - "Row limit reduced to %d following incomplete response.\n", - limit); + if (cap_frags) { + frags = max(2, frags / 2); + if (debug) + fprintf(stderr, + "Frag limit reduced to %d following incomplete response.\n", + frags); + } else { + 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; @@ -2595,9 +2614,16 @@ collect_mru_list( * no less than 3 rows fit in each packet, capped at * our best guess at the server's row limit. */ - if (!qres) - limit = min3(3 * MAXFRAGS, ntpd_row_limit, - max(limit + 1, limit * 33 / 32)); + if (!qres) { + if (cap_frags) { + frags = min(MAXFRAGS, frags + 1); + } else { + limit = min3(3 * MAXFRAGS, + ntpd_row_limit, + max(limit + 1, + limit * 33 / 32)); + } + } /* * prepare next query with as many address and last-seen * timestamps as will fit in a single packet. @@ -2605,8 +2631,14 @@ collect_mru_list( req = req_buf; req_end = req_buf + sizeof(req_buf); #define REQ_ROOM (req_end - req) - snprintf(req, REQ_ROOM, "nonce=%s, limit=%d%s", nonce, - limit, parms); + snprintf(req, REQ_ROOM, "nonce=%s, %s=%d%s", nonce, + (cap_frags) + ? "frags" + : "limit", + (cap_frags) + ? frags + : limit, + parms); req += strlen(req); nonce_uses++; if (nonce_uses >= 4) { diff --git a/util/ntp-keygen.c b/util/ntp-keygen.c index 4301e36257..c1a2b3023a 100644 --- a/util/ntp-keygen.c +++ b/util/ntp-keygen.c @@ -347,6 +347,7 @@ main( passwd1 = hostbuf; passwd2 = NULL; GETTIMEOFDAY(&tv, NULL); + ntp_srandom((u_long)(tv.tv_sec + tv.tv_usec)); epoch = tv.tv_sec; fstamp = (u_int)(epoch + JAN_1970); @@ -817,7 +818,6 @@ gen_md5( #endif /* OPENSSL */ str = fheader("MD5key", id, groupname); - ntp_srandom((u_long)epoch); for (i = 1; i <= MD5KEYS; i++) { for (j = 0; j < MD5SIZE; j++) { int temp;