1*eabc0478Schristos /* $NetBSD: utilities.c,v 1.7 2024/08/18 20:47:20 christos Exp $ */ 2abb0f93cSkardel 3f003fb54Skardel #include <config.h> 4abb0f93cSkardel #include "utilities.h" 5f003fb54Skardel #include <assert.h> 6abb0f93cSkardel 7abb0f93cSkardel /* Display a NTP packet in hex with leading address offset 8abb0f93cSkardel * e.g. offset: value, 0: ff 1: fe ... 255: 00 9abb0f93cSkardel */ 10abb0f93cSkardel void 11abb0f93cSkardel pkt_output ( 12abb0f93cSkardel struct pkt *dpkg, 13abb0f93cSkardel int pkt_length, 14abb0f93cSkardel FILE *output 15abb0f93cSkardel ) 16abb0f93cSkardel { 17abb0f93cSkardel register int a; 18abb0f93cSkardel u_char *pkt; 19abb0f93cSkardel 20abb0f93cSkardel pkt = (u_char *)dpkg; 21abb0f93cSkardel 22abb0f93cSkardel fprintf(output, HLINE); 23abb0f93cSkardel 24abb0f93cSkardel for (a = 0; a < pkt_length; a++) { 25abb0f93cSkardel if (a > 0 && a % 8 == 0) 26abb0f93cSkardel fprintf(output, "\n"); 27abb0f93cSkardel 284eea345dSchristos fprintf(output, "%3d: %02x ", a, pkt[a]); 29abb0f93cSkardel } 30abb0f93cSkardel 31abb0f93cSkardel fprintf(output, "\n"); 32abb0f93cSkardel fprintf(output, HLINE); 33abb0f93cSkardel } 34abb0f93cSkardel 35abb0f93cSkardel /* Output a long floating point value in hex in the style described above 36abb0f93cSkardel */ 37abb0f93cSkardel void 38abb0f93cSkardel l_fp_output( 39abb0f93cSkardel l_fp * ts, 40abb0f93cSkardel FILE * output 41abb0f93cSkardel ) 42abb0f93cSkardel { 438585484eSchristos fprintf(output, "%s\n", prettydate(ts)); 44abb0f93cSkardel } 45abb0f93cSkardel 46abb0f93cSkardel /* Output a long floating point value in binary in the style described above 47abb0f93cSkardel */ 48abb0f93cSkardel void 49abb0f93cSkardel l_fp_output_bin ( 50abb0f93cSkardel l_fp *ts, 51abb0f93cSkardel FILE *output 52abb0f93cSkardel ) 53abb0f93cSkardel { 54abb0f93cSkardel register int a, b; 55abb0f93cSkardel 56abb0f93cSkardel fprintf(output, HLINE); 57abb0f93cSkardel 58abb0f93cSkardel for(a=0; a<8; a++) { 59abb0f93cSkardel short tmp = ((unsigned char *) ts)[a]; 60abb0f93cSkardel tmp++; 61abb0f93cSkardel 62abb0f93cSkardel fprintf(output, "%i: ", a); 63abb0f93cSkardel 64abb0f93cSkardel for(b=7; b>=0; b--) { 65abb0f93cSkardel int texp = (int) pow(2, b); 66abb0f93cSkardel 67abb0f93cSkardel if(tmp - texp > 0) { 68abb0f93cSkardel fprintf(output, "1"); 69abb0f93cSkardel tmp -= texp; 70abb0f93cSkardel } 71abb0f93cSkardel else { 72abb0f93cSkardel fprintf(output, "0"); 73abb0f93cSkardel } 74abb0f93cSkardel } 75abb0f93cSkardel 76abb0f93cSkardel fprintf(output, " "); 77abb0f93cSkardel } 78abb0f93cSkardel 79abb0f93cSkardel fprintf(output, "\n"); 80abb0f93cSkardel fprintf(output, HLINE); 81abb0f93cSkardel } 82abb0f93cSkardel 83abb0f93cSkardel /* Output a long floating point value in decimal in the style described above 84abb0f93cSkardel */ 85abb0f93cSkardel void 86abb0f93cSkardel l_fp_output_dec ( 87abb0f93cSkardel l_fp *ts, 88abb0f93cSkardel FILE *output 89abb0f93cSkardel ) 90abb0f93cSkardel { 91abb0f93cSkardel register int a; 92abb0f93cSkardel 93abb0f93cSkardel fprintf(output, HLINE); 94abb0f93cSkardel 95abb0f93cSkardel for(a=0; a<8; a++) 96abb0f93cSkardel fprintf(output, "%i: %i \t", a, ((unsigned char *) ts)[a]); 97abb0f93cSkardel 98abb0f93cSkardel fprintf(output, "\n"); 99abb0f93cSkardel fprintf(output, HLINE); 100abb0f93cSkardel 101abb0f93cSkardel } 102abb0f93cSkardel 103abb0f93cSkardel /* Convert a struct addrinfo to a string containing the address in style 104abb0f93cSkardel * of inet_ntoa 105abb0f93cSkardel */ 106abb0f93cSkardel char * 107abb0f93cSkardel addrinfo_to_str ( 1088585484eSchristos const struct addrinfo *addr 109abb0f93cSkardel ) 110abb0f93cSkardel { 111f003fb54Skardel sockaddr_u s; 112abb0f93cSkardel 1138585484eSchristos ZERO(s); 114f003fb54Skardel memcpy(&s, addr->ai_addr, min(sizeof(s), addr->ai_addrlen)); 115abb0f93cSkardel 116f003fb54Skardel return ss_to_str(&s); 117abb0f93cSkardel } 118abb0f93cSkardel 1198585484eSchristos 120abb0f93cSkardel /* Convert a sockaddr_u to a string containing the address in 121abb0f93cSkardel * style of inet_ntoa 122abb0f93cSkardel * Why not switch callers to use stoa from libntp? No free() needed 123abb0f93cSkardel * in that case. 124abb0f93cSkardel */ 125abb0f93cSkardel char * 126abb0f93cSkardel ss_to_str( 127abb0f93cSkardel sockaddr_u *saddr 128abb0f93cSkardel ) 129abb0f93cSkardel { 1308585484eSchristos return estrdup(stoa(saddr)); 131abb0f93cSkardel } 1328585484eSchristos 1338585484eSchristos 134f003fb54Skardel /* 135f003fb54Skardel * Converts a struct tv to a date string 136abb0f93cSkardel */ 137abb0f93cSkardel char * 138abb0f93cSkardel tv_to_str( 139f003fb54Skardel const struct timeval *tv 140abb0f93cSkardel ) 141abb0f93cSkardel { 142f003fb54Skardel const size_t bufsize = 48; 143f003fb54Skardel char *buf; 144f003fb54Skardel time_t gmt_time, local_time; 145*eabc0478Schristos struct tm *ptm, tm_local; 146*eabc0478Schristos int hh, mm, lto, isdst; 147abb0f93cSkardel 148f003fb54Skardel /* 149f003fb54Skardel * convert to struct tm in UTC, then intentionally feed 150f003fb54Skardel * that tm to mktime() which expects local time input, to 151f003fb54Skardel * derive the offset from UTC to local time. 152*eabc0478Schristos * Need to retrieve dst flag from localtime first for mktime. 153f003fb54Skardel */ 154f003fb54Skardel gmt_time = tv->tv_sec; 155*eabc0478Schristos ptm = localtime(&gmt_time); 156*eabc0478Schristos memcpy (&tm_local, ptm, sizeof(tm_local)); 157*eabc0478Schristos isdst = ptm->tm_isdst; 158*eabc0478Schristos ptm = gmtime(&gmt_time); 159*eabc0478Schristos ptm->tm_isdst = isdst; 160*eabc0478Schristos local_time = mktime(ptm); 161abb0f93cSkardel 162f003fb54Skardel /* Local timezone offsets should never cause an overflow. Yeah. */ 163f003fb54Skardel lto = difftime(local_time, gmt_time); 164f003fb54Skardel lto /= 60; 165f003fb54Skardel hh = lto / 60; 166f003fb54Skardel mm = abs(lto % 60); 167abb0f93cSkardel 168f003fb54Skardel buf = emalloc(bufsize); 169f003fb54Skardel snprintf(buf, bufsize, 170f003fb54Skardel "%d-%.2d-%.2d %.2d:%.2d:%.2d.%.6d (%+03d%02d)", 171*eabc0478Schristos tm_local.tm_year + 1900, 172*eabc0478Schristos tm_local.tm_mon + 1, 173*eabc0478Schristos tm_local.tm_mday, 174*eabc0478Schristos tm_local.tm_hour, 175*eabc0478Schristos tm_local.tm_min, 176*eabc0478Schristos tm_local.tm_sec, 177f003fb54Skardel (int)tv->tv_usec, 178f003fb54Skardel hh, 179f003fb54Skardel mm); 180abb0f93cSkardel 181abb0f93cSkardel return buf; 182abb0f93cSkardel } 183abb0f93cSkardel 184abb0f93cSkardel 1858585484eSchristos /* 1868585484eSchristos * 1878585484eSchristos * hostnameaddr() 1888585484eSchristos * 1898585484eSchristos * Formats the hostname and resulting numeric IP address into a string, 1908585484eSchristos * avoiding duplication if the "hostname" was in fact a numeric address. 1918585484eSchristos * 1928585484eSchristos */ 1938585484eSchristos const char * 1948585484eSchristos hostnameaddr( 1958585484eSchristos const char * hostname, 1968585484eSchristos const sockaddr_u * addr 1978585484eSchristos ) 1988585484eSchristos { 1998585484eSchristos const char * addrtxt; 2008585484eSchristos char * result; 2018585484eSchristos int cnt; 202abb0f93cSkardel 2038585484eSchristos addrtxt = stoa(addr); 2048585484eSchristos LIB_GETBUF(result); 2058585484eSchristos if (strcmp(hostname, addrtxt)) 2068585484eSchristos cnt = snprintf(result, LIB_BUFLENGTH, "%s %s", 2078585484eSchristos hostname, addrtxt); 2088585484eSchristos else 2098585484eSchristos cnt = snprintf(result, LIB_BUFLENGTH, "%s", addrtxt); 2108585484eSchristos if (cnt >= LIB_BUFLENGTH) 2118585484eSchristos snprintf(result, LIB_BUFLENGTH, 2128585484eSchristos "hostnameaddr ERROR have %d (%d needed)", 2138585484eSchristos LIB_BUFLENGTH, cnt + 1); 214abb0f93cSkardel 2158585484eSchristos return result; 2168585484eSchristos } 217