xref: /netbsd-src/external/bsd/ntp/dist/libntp/socktohost.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1 /*	$NetBSD: socktohost.c,v 1.7 2024/08/18 20:47:13 christos Exp $	*/
2 
3 /*
4  * socktoa - return a numeric host name from a sockaddr_storage structure
5  */
6 #include <config.h>
7 #include <sys/types.h>
8 #ifdef HAVE_SYS_SOCKET_H
9 #include <sys/socket.h>
10 #endif
11 #ifdef HAVE_NETINET_IN_H
12 #include <netinet/in.h>
13 #endif
14 
15 #include <arpa/inet.h>
16 
17 #include <stdio.h>
18 
19 #include "ntp_fp.h"
20 #include "ntp_stdlib.h"
21 #include "ntp.h"
22 #include "ntp_debug.h"
23 
24 
25 const char *
26 socktohost(
27 	const sockaddr_u *sock
28 	)
29 {
30 	const char		svc[] = "ntp";
31 	char *			pbuf;
32 	char *			pliar;
33 	int			gni_flags;
34 	struct addrinfo		hints;
35 	struct addrinfo *	alist;
36 	struct addrinfo *	ai;
37 	sockaddr_u		addr;
38 	size_t			octets;
39 	int			a_info;
40 	int			saved_errno;
41 
42 	saved_errno = socket_errno();
43 
44 	/* reverse the address to purported DNS name */
45 	LIB_GETBUF(pbuf);
46 	gni_flags = NI_DGRAM | NI_NAMEREQD;
47 	if (getnameinfo(&sock->sa, SOCKLEN(sock), pbuf, LIB_BUFLENGTH,
48 			NULL, 0, gni_flags)) {
49 		errno = saved_errno;
50 		return stoa(sock);	/* use address */
51 	}
52 
53 	TRACE(1, ("%s reversed to %s\n", stoa(sock), pbuf));
54 
55 	/*
56 	 * Resolve the reversed name and make sure the reversed address
57 	 * is among the results.
58 	 */
59 	ZERO(hints);
60 	hints.ai_family = AF(sock);
61 	hints.ai_protocol = IPPROTO_UDP;
62 	hints.ai_socktype = SOCK_DGRAM;
63 	hints.ai_flags = 0;
64 	alist = NULL;
65 
66 	a_info = getaddrinfo(pbuf, svc, &hints, &alist);
67 	if (a_info == EAI_NONAME
68 #ifdef EAI_NODATA
69 	    || a_info == EAI_NODATA
70 #endif
71 	   ) {
72 		hints.ai_flags = AI_CANONNAME;
73 #ifdef AI_ADDRCONFIG
74 		hints.ai_flags |= AI_ADDRCONFIG;
75 #endif
76 		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
77 	}
78 #ifdef AI_ADDRCONFIG
79 	/* Some older implementations don't like AI_ADDRCONFIG. */
80 	if (a_info == EAI_BADFLAGS) {
81 		hints.ai_flags &= ~AI_ADDRCONFIG;
82 		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
83 	}
84 #endif
85 	if (a_info)
86 		goto forward_fail;
87 
88 	INSIST(alist != NULL);
89 
90 	for (ai = alist; ai != NULL; ai = ai->ai_next) {
91 		/*
92 		 * Make a convenience sockaddr_u copy from ai->ai_addr
93 		 * because casting from sockaddr * to sockaddr_u * is
94 		 * risking alignment problems on platforms where
95 		 * sockaddr_u has stricter alignment than sockaddr,
96 		 * such as sparc.
97 		 */
98 		ZERO_SOCK(&addr);
99 		octets = min(sizeof(addr), ai->ai_addrlen);
100 		memcpy(&addr, ai->ai_addr, octets);
101 		if (SOCK_EQ(sock, &addr))
102 			break;
103 	}
104 	freeaddrinfo(alist);
105 
106 	if (ai != NULL) {
107 		errno = saved_errno;
108 		return pbuf;	/* forward check passed */
109 	}
110 
111     forward_fail:
112 	TRACE(1, ("%s forward check lookup fail: %s\n", pbuf,
113 		  gai_strerror(a_info)));
114 	LIB_GETBUF(pliar);
115 	snprintf(pliar, LIB_BUFLENGTH, "%s (%s)", stoa(sock), pbuf);
116 
117 	errno = saved_errno;
118 	return pliar;
119 }
120