xref: /netbsd-src/external/bsd/ntp/dist/libntp/numtoa.c (revision 3117ece4fc4a4ca4489ba793710b60b0d26bab6c)
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 *
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 *
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