xref: /netbsd-src/external/bsd/ntp/dist/sntp/utilities.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
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