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