const char * modetoa( size_t mode ) { char *bp; static const char * const modestrings[] = { "unspec", "sym_active", "sym_passive", "client", "server", "broadcast", "control", "private", "bclient", }; if (mode >= COUNTOF(modestrings)) { LIB_GETBUF(bp); snprintf(bp, LIB_BUFLENGTH, "mode#%zu", mode); return bp; } return modestrings[mode]; }
char * socktoa( const sockaddr_u *sock ) { register char *buffer; LIB_GETBUF(buffer); if (NULL == sock) strncpy(buffer, "(null)", LIB_BUFLENGTH); else { switch(AF(sock)) { case AF_INET: case AF_UNSPEC: inet_ntop(AF_INET, PSOCK_ADDR4(sock), buffer, LIB_BUFLENGTH); break; case AF_INET6: inet_ntop(AF_INET6, PSOCK_ADDR6(sock), buffer, LIB_BUFLENGTH); break; default: snprintf(buffer, LIB_BUFLENGTH, "(socktoa unknown family %d)", AF(sock)); } } return buffer; }
char * numtohost( u_int32 netnum ) { char *bp; struct hostent *hp; /* * This is really gross, but saves lots of hanging looking for * hostnames for the radio clocks. Don't bother looking up * addresses on the loopback network except for the loopback * host itself. */ if ((((ntohl(netnum) & LOOPBACKNETMASK) == LOOPBACKNET) && (ntohl(netnum) != LOOPBACKHOST)) || ((hp = gethostbyaddr((char *)&netnum, sizeof netnum, AF_INET)) == 0)) return numtoa(netnum); LIB_GETBUF(bp); bp[LIB_BUFLENGTH-1] = '\0'; (void) strncpy(bp, hp->h_name, LIB_BUFLENGTH-1); return bp; }
const char * humanlogtime(void) { char * bp; time_t cursec; struct tm tmbuf, *tm; cursec = time(NULL); tm = localtime_r(&cursec, &tmbuf); if (!tm) return "-- --- --:--:--"; LIB_GETBUF(bp); #ifdef ENABLE_CLASSIC_MODE const char * const months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; snprintf(bp, LIB_BUFLENGTH, "%2d %s %02d:%02d:%02d", tm->tm_mday, months[tm->tm_mon], tm->tm_hour, tm->tm_min, tm->tm_sec); #else /* ISO 8601 is a better format, sort order equals time order */ snprintf(bp, LIB_BUFLENGTH, "%02d-%02dT%02d:%02d:%02d", tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); #endif /* ENABLE_CLASSIC_MODE */ return bp; }
/* * keytype_from_text returns OpenSSL NID for digest by name, and * optionally the associated digest length. * * Used by ntpd authreadkeys(), ntpq keytype() */ int keytype_from_text( const char *text, size_t *pdigest_len ) { int key_type; u_int digest_len; #ifdef HAVE_OPENSSL const u_long max_digest_len = MAX_MAC_LEN - sizeof(keyid_t); uint8_t digest[EVP_MAX_MD_SIZE]; char * upcased; char * pch; EVP_MD_CTX ctx; /* * OpenSSL digest short names are capitalized, so uppercase the * digest name before passing to OBJ_sn2nid(). If it is not * recognized but begins with 'M' use NID_md5 to be consistent * with past behavior. */ INIT_SSL(); LIB_GETBUF(upcased); strlcpy(upcased, text, LIB_BUFLENGTH); for (pch = upcased; '\0' != *pch; pch++) *pch = (char)toupper((unsigned char)*pch); key_type = OBJ_sn2nid(upcased); #else key_type = 0; #endif if (!key_type && 'm' == tolower((unsigned char)text[0])) key_type = NID_md5; if (!key_type) return 0; if (NULL != pdigest_len) { #ifdef HAVE_OPENSSL EVP_DigestInit(&ctx, EVP_get_digestbynid(key_type)); EVP_DigestFinal(&ctx, digest, &digest_len); if (digest_len > max_digest_len) { fprintf(stderr, "key type %s %u octet digests are too big, max %lu\n", keytype_name(key_type), digest_len, max_digest_len); msyslog(LOG_ERR, "key type %s %u octet digests are too big, max %lu", keytype_name(key_type), digest_len, max_digest_len); return 0; } #else digest_len = 16; #endif *pdigest_len = digest_len; } return key_type; }
/* * general fractional timestamp formatting * * Many pieces of ntpd require a machine with two's complement * representation of signed integers, so we don't go through the whole * rigamarole of creating fully portable code here. But we have to stay * away from signed integer overflow, as this might cause trouble even * with two's complement representation. */ const char * format_time_fraction( time_t secs, long frac, int prec ) { char * cp; u_int prec_u; u_time secs_u; u_int u; long fraclimit; int notneg; /* flag for non-negative value */ ldiv_t qr; DEBUG_REQUIRE(prec != 0); LIB_GETBUF(cp); secs_u = (u_time)secs; /* check if we need signed or unsigned mode */ notneg = (prec < 0); prec_u = abs(prec); /* fraclimit = (long)pow(10, prec_u); */ for (fraclimit = 10, u = 1; u < prec_u; u++) { DEBUG_INSIST(fraclimit < fraclimit * 10); fraclimit *= 10; } /* * Since conversion to string uses lots of divisions anyway, * there's no big extra penalty for normalisation. We do it for * consistency. */ if (frac < 0 || frac >= fraclimit) { qr = ldiv(frac, fraclimit); if (qr.rem < 0) { qr.quot--; qr.rem += fraclimit; } secs_u += (time_t)qr.quot; frac = qr.rem; } /* Get the absolute value of the split representation time. */ notneg = notneg || ((time_t)secs_u >= 0); if (!notneg) { secs_u = ~secs_u; if (0 == frac) secs_u++; else frac = fraclimit - frac; } /* finally format the data and return the result */ snprintf(cp, LIB_BUFLENGTH, "%s%" UTIME_FORMAT ".%0*ld", notneg? "" : "-", secs_u, prec_u, frac); return cp; }
const char * refnumtoa( sockaddr_u *num ) { u_int32 netnum; char *buf; const char *rclock; if (!ISREFCLOCKADR(num)) return socktoa(num); LIB_GETBUF(buf); netnum = SRCADR(num); rclock = clockname((int)((u_long)netnum >> 8) & 0xff); if (rclock != NULL) snprintf(buf, LIB_BUFLENGTH, "%s(%lu)", rclock, (u_long)netnum & 0xff); else snprintf(buf, LIB_BUFLENGTH, "REFCLK(%lu,%lu)", ((u_long)netnum >> 8) & 0xff, (u_long)netnum & 0xff); return buf; }
static char * fmt_blong( unsigned long val, int cnt ) { char *buf, *s; int i = cnt; val <<= 32 - cnt; LIB_GETBUF(buf); s = buf; while (i--) { if (val & 0x80000000) { *s++ = '1'; } else { *s++ = '0'; } val <<= 1; } *s = '\0'; return buf; }
/* * socktoa - return a numeric host name from a sockaddr_storage structure */ const char * socktoa( const sockaddr_u *sock ) { int saved_errno; char * res; char * addr; u_long scope; saved_errno = errno; LIB_GETBUF(res); if (NULL == sock) { strlcpy(res, "(null)", LIB_BUFLENGTH); } else { switch(AF(sock)) { case AF_INET: case AF_UNSPEC: inet_ntop(AF_INET, PSOCK_ADDR4(sock), res, LIB_BUFLENGTH); break; case AF_INET6: inet_ntop(AF_INET6, PSOCK_ADDR6(sock), res, LIB_BUFLENGTH); scope = SCOPE_VAR(sock); if (0 != scope && !strchr(res, '%')) { addr = res; LIB_GETBUF(res); snprintf(res, LIB_BUFLENGTH, "%s%%%lu", addr, scope); res[LIB_BUFLENGTH - 1] = '\0'; } break; default: snprintf(res, LIB_BUFLENGTH, "(socktoa unknown family %d)", AF(sock)); } } errno = saved_errno; return res; }
/* * decode_bitflags() * * returns a human-readable string with a keyword from tab for each bit * set in bits, separating multiple entries with text of sep2. */ static const char * decode_bitflags( int bits, const char * sep2, const struct codestring * tab, size_t tab_ct ) { const char * sep; char * buf; char * pch; char * lim; size_t b; int rc; int saved_errno; /* for use in DPRINTF with %m */ saved_errno = errno; LIB_GETBUF(buf); pch = buf; lim = buf + LIB_BUFLENGTH; sep = ""; for (b = 0; b < tab_ct; b++) { if (tab[b].code & bits) { rc = snprintf(pch, (lim - pch), "%s%s", sep, tab[b].string); if (rc < 0) goto toosmall; pch += (u_int)rc; if (pch >= lim) goto toosmall; sep = sep2; } } return buf; toosmall: snprintf(buf, LIB_BUFLENGTH, "decode_bitflags(%s) can't decode 0x%x in %d bytes", (tab == peer_st_bits) ? "peer_st" : #ifdef KERNEL_PLL (tab == k_st_bits) ? "kern_st" : #endif "", bits, (int)LIB_BUFLENGTH); errno = saved_errno; return buf; }
char * ntp_strerror( int code ) { char * buf; LIB_GETBUF(buf); strerror_r(code, buf, LIB_BUFLENGTH); return buf; }
char * inttoa( long ival ) { register char *buf; LIB_GETBUF(buf); (void) sprintf(buf, "%ld", (long)ival); return buf; }
char * inttoa( long val ) { register char *buf; LIB_GETBUF(buf); snprintf(buf, sizeof(buf), "%ld", val); return buf; }
char * uinttoa( u_long uval ) { register char *buf; LIB_GETBUF(buf); snprintf(buf, LIB_BUFLENGTH, "%lu", uval); return buf; }
char * utvtoa( const struct timeval *tv ) { register char *buf; LIB_GETBUF(buf); (void) sprintf(buf, "%lu.%06lu", (u_long)tv->tv_sec, (u_long)tv->tv_usec); return buf; }
/* * lstostr - prettyprint NTP seconds */ static char * lstostr( const vint64 * ts) { char * buf; struct calendar tm; LIB_GETBUF(buf); ntpcal_ntp64_to_date(&tm, ts); snprintf(buf, LIB_BUFLENGTH, "%04d-%02d-%02dT%02d:%02dZ", tm.year, tm.month, tm.monthday, tm.hour, tm.minute); return buf; }
char * socktohost( struct sockaddr_storage* sock ) { register char *buffer; LIB_GETBUF(buffer); if (getnameinfo((struct sockaddr *)sock, SOCKLEN(sock), buffer, LIB_BUFLENGTH /* NI_MAXHOST*/, NULL, 0, 0)) return stoa(sock); return buffer; }
char * humanlogtime(void) { char *bp; time_t cursec = time((time_t *) 0); struct tm *tm = localtime(&cursec); LIB_GETBUF(bp); (void) sprintf(bp, "%2d %s %02d:%02d:%02d", tm->tm_mday, months[tm->tm_mon], tm->tm_hour, tm->tm_min, tm->tm_sec); return bp; }
static char * common_prettydate( l_fp *ts, int local ) { static const char pfmt0[] = "%08lx.%08lx %s, %s %2d %4d %2d:%02d:%02d.%03u"; static const char pfmt1[] = "%08lx.%08lx [%s, %s %2d %4d %2d:%02d:%02d.%03u UTC]"; char *bp; struct tm *tm; u_int msec; u_int32 ntps; vint64 sec; LIB_GETBUF(bp); /* get & fix milliseconds */ ntps = ts->l_ui; msec = ts->l_uf / 4294967; /* fract / (2 ** 32 / 1000) */ if (msec >= 1000u) { msec -= 1000u; ntps++; } sec = ntpcal_ntp_to_time(ntps, NULL); tm = get_struct_tm(&sec, local); if (!tm) { /* * get a replacement, but always in UTC, using * ntpcal_time_to_date() */ struct calendar jd; ntpcal_time_to_date(&jd, &sec); snprintf(bp, LIB_BUFLENGTH, local ? pfmt1 : pfmt0, (u_long)ts->l_ui, (u_long)ts->l_uf, daynames[jd.weekday], months[jd.month-1], jd.monthday, jd.year, jd.hour, jd.minute, jd.second, msec); } else snprintf(bp, LIB_BUFLENGTH, pfmt0, (u_long)ts->l_ui, (u_long)ts->l_uf, daynames[tm->tm_wday], months[tm->tm_mon], tm->tm_mday, 1900 + tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec, msec); return bp; }
static char * fmt_hex( unsigned char *bufp, int length ) { char *buf; int i; LIB_GETBUF(buf); for (i = 0; i < length; i++) { sprintf(buf+i*2, "%02x", bufp[i]); } return buf; }
const char * symbname( u_short token ) { char *name; if (token < COUNTOF(symb) && symb[token] != NULL) { name = symb[token]; } else { LIB_GETBUF(name); snprintf(name, LIB_BUFLENGTH, "%d", token); } return name; }
char * numtoa( u_int32 num ) { register u_int32 netnum; register char *buf; netnum = ntohl(num); LIB_GETBUF(buf); snprintf(buf, LIB_BUFLENGTH, "%lu.%lu.%lu.%lu", ((u_long)netnum >> 24) & 0xff, ((u_long)netnum >> 16) & 0xff, ((u_long)netnum >> 8) & 0xff, (u_long)netnum & 0xff); return buf; }
/* * fstostr - prettyprint NTP seconds */ char * fstostr( time_t ntp_stamp ) { char * buf; struct calendar tm; LIB_GETBUF(buf); if (ntpcal_ntp_to_date(&tm, (u_int32)ntp_stamp, NULL) < 0) snprintf(buf, LIB_BUFLENGTH, "ntpcal_ntp_to_date: %ld: range error", (long)ntp_stamp); else snprintf(buf, LIB_BUFLENGTH, "%04d%02d%02d%02d%02d", tm.year, tm.month, tm.monthday, tm.hour, tm.minute); return buf; }
static char * fmt_flt( unsigned int sign, unsigned long mh, unsigned long ml, unsigned long ch ) { char *buf; LIB_GETBUF(buf); sprintf(buf, "%c %s %s %s", sign ? '-' : '+', fmt_blong(ch, 11), fmt_blong(mh, 20), fmt_blong(ml, 32)); return buf; }
/* * statustoa - return a descriptive string for a peer status */ char * statustoa( int type, int st ) { char * cb; char * cc; u_char pst; LIB_GETBUF(cb); switch (type) { case TYPE_SYS: snprintf(cb, LIB_BUFLENGTH, "%s, %s, %s, %s", getcode(CTL_SYS_LI(st), leap_codes), getcode(CTL_SYS_SOURCE(st), sync_codes), getevents(CTL_SYS_NEVNT(st)), getcode(CTL_SYS_EVENT(st), sys_codes)); break; case TYPE_PEER: pst = (u_char)CTL_PEER_STATVAL(st); snprintf(cb, LIB_BUFLENGTH, "%s, %s, %s", peer_st_flags(pst), getcode(pst & 0x7, select_codes), getevents(CTL_PEER_NEVNT(st))); if (CTL_PEER_EVENT(st) != EVNT_UNSPEC) { cc = cb + strlen(cb); snprintf(cc, LIB_BUFLENGTH - (cc - cb), ", %s", getcode(CTL_PEER_EVENT(st), peer_codes)); } break; case TYPE_CLOCK: snprintf(cb, LIB_BUFLENGTH, "%s, %s", getevents(CTL_SYS_NEVNT(st)), getcode((st) & 0xf, clock_codes)); break; } return cb; }
/* * lstostr - prettyprint NTP seconds */ static const char * lstostr( const vint64 * ts) { char * buf; struct calendar tm; LIB_GETBUF(buf); if ( ! (ts->d_s.hi >= 0 && ntpcal_ntp64_to_date(&tm, ts) >= 0)) snprintf(buf, LIB_BUFLENGTH, "%s", "9999-12-31T23:59:59Z"); else snprintf(buf, LIB_BUFLENGTH, "%04d-%02d-%02dT%02d:%02d:%02dZ", tm.year, tm.month, tm.monthday, tm.hour, tm.minute, tm.second); return buf; }
/* * getevents - return a descriptive string for the event count */ static const char * getevents( int cnt ) { char * buf; if (cnt == 0) return "no events"; LIB_GETBUF(buf); snprintf(buf, LIB_BUFLENGTH, "%d event%s", cnt, (1 == cnt) ? "" : "s"); return buf; }
/* * getcode - return string corresponding to code */ static const char * getcode( int code, const struct codestring * codetab ) { char * buf; while (codetab->code != -1) { if (codetab->code == code) return codetab->string; codetab++; } LIB_GETBUF(buf); snprintf(buf, LIB_BUFLENGTH, "%s_%d", codetab->string, code); return buf; }
/* * humantime() -- like humanlogtime() but without date, and with the * time to display given as an argument. */ const char * humantime( time_t cursec ) { char * bp; struct tm * tm; tm = localtime(&cursec); if (!tm) return "--:--:--"; LIB_GETBUF(bp); snprintf(bp, LIB_BUFLENGTH, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); return bp; }
static char * fmt_hex( unsigned char *bufp, int length ) { char * buf; char hex[4]; int i; LIB_GETBUF(buf); buf[0] = '\0'; for (i = 0; i < length; i++) { snprintf(hex, sizeof(hex), "%02x", bufp[i]); strlcat(buf, hex, LIB_BUFLENGTH); } return buf; }