1 /*        $NetBSD: numtoa.c,v 1.6 2024/08/18 20:47:13 christos Exp $  */
2 
3 /*
4  * numtoa - return asciized network numbers store in local array space
5  */
6 #include <config.h>
7 
8 #include <sys/types.h>
9 #ifdef HAVE_NETINET_IN_H
10 #include <netinet/in.h>                 /* ntohl */
11 #endif
12 
13 #include <stdio.h>
14 #include <ctype.h>
15 
16 #include "ntp_fp.h"
17 #include "ntp_stdlib.h"
18 
19 char *
numtoa(u_int32 num)20 numtoa(
21           u_int32 num
22           )
23 {
24           register u_int32 netnum;
25           register char *buf;
26 
27           netnum = ntohl(num);
28           LIB_GETBUF(buf);
29           snprintf(buf, LIB_BUFLENGTH, "%lu.%lu.%lu.%lu",
30                      ((u_long)netnum >> 24) & 0xff,
31                      ((u_long)netnum >> 16) & 0xff,
32                      ((u_long)netnum >> 8) & 0xff,
33                      (u_long)netnum & 0xff);
34           return buf;
35 }
36 
37 
38 /*
39  * Convert a refid & stratum to a string.  If stratum is negative and the
40  * refid consists entirely of graphic chars, up to an optional
41  * terminating zero, display as text similar to stratum 0 & 1.
42  */
43 const char *
refid_str(u_int32 refid,int stratum)44 refid_str(
45           u_int32   refid,
46           int       stratum
47           )
48 {
49           char *    text;
50           size_t    tlen;
51           char *    cp;
52           int       printable;
53 
54           /*
55            * ntpd can have stratum = 0 and refid 127.0.0.1 in orphan mode.
56            * https://bugs.ntp.org/3854.  Mirror the refid logic in timer().
57            */
58           if (0 == stratum && LOOPBACKADR_N == refid) {
59                     return ".ORPH.";
60           }
61           printable = FALSE;
62           if (stratum < 2) {
63                     text = lib_getbuf();
64                     text[0] = '.';
65                     memcpy(&text[1], &refid, sizeof(refid));
66                     text[1 + sizeof(refid)] = '\0';
67                     tlen = strlen(text);
68                     text[tlen] = '.';
69                     text[tlen + 1] = '\0';
70                     /*
71                      * Now make sure the contents are 'graphic'.
72                      *
73                      * This refid is expected to be up to 4 printable ASCII.
74                      * isgraph() is similar to isprint() but excludes space.
75                      * If any character is not graphic, replace it with a '?'.
76                      * This will at least alert the viewer of a problem.
77                      */
78                     for (cp = text + 1; '\0' != *cp; ++cp) {
79                               if (!isgraph((int)*cp)) {
80                                         printable = FALSE;
81                                         *cp = '?';
82                               }
83                     }
84                     if (   (stratum < 0 && printable)
85                         || stratum < 2) {
86                               return text;
87                     }
88           }
89           return numtoa(refid);
90 }
91 
92