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