xref: /netbsd-src/external/bsd/ntp/dist/libntp/socktohost.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1*eabc0478Schristos /*	$NetBSD: socktohost.c,v 1.7 2024/08/18 20:47:13 christos Exp $	*/
2abb0f93cSkardel 
3abb0f93cSkardel /*
4abb0f93cSkardel  * socktoa - return a numeric host name from a sockaddr_storage structure
5abb0f93cSkardel  */
68585484eSchristos #include <config.h>
7abb0f93cSkardel #include <sys/types.h>
8abb0f93cSkardel #ifdef HAVE_SYS_SOCKET_H
9abb0f93cSkardel #include <sys/socket.h>
10abb0f93cSkardel #endif
11abb0f93cSkardel #ifdef HAVE_NETINET_IN_H
12abb0f93cSkardel #include <netinet/in.h>
13abb0f93cSkardel #endif
14abb0f93cSkardel 
15abb0f93cSkardel #include <arpa/inet.h>
16abb0f93cSkardel 
17abb0f93cSkardel #include <stdio.h>
18abb0f93cSkardel 
19abb0f93cSkardel #include "ntp_fp.h"
20abb0f93cSkardel #include "ntp_stdlib.h"
21abb0f93cSkardel #include "ntp.h"
228585484eSchristos #include "ntp_debug.h"
23abb0f93cSkardel 
24abb0f93cSkardel 
258585484eSchristos const char *
26abb0f93cSkardel socktohost(
27f003fb54Skardel 	const sockaddr_u *sock
28abb0f93cSkardel 	)
29abb0f93cSkardel {
308585484eSchristos 	const char		svc[] = "ntp";
318585484eSchristos 	char *			pbuf;
328585484eSchristos 	char *			pliar;
338585484eSchristos 	int			gni_flags;
348585484eSchristos 	struct addrinfo		hints;
358585484eSchristos 	struct addrinfo *	alist;
368585484eSchristos 	struct addrinfo *	ai;
378585484eSchristos 	sockaddr_u		addr;
388585484eSchristos 	size_t			octets;
398585484eSchristos 	int			a_info;
408b8da087Schristos 	int			saved_errno;
418b8da087Schristos 
428b8da087Schristos 	saved_errno = socket_errno();
43abb0f93cSkardel 
448585484eSchristos 	/* reverse the address to purported DNS name */
458585484eSchristos 	LIB_GETBUF(pbuf);
468585484eSchristos 	gni_flags = NI_DGRAM | NI_NAMEREQD;
478585484eSchristos 	if (getnameinfo(&sock->sa, SOCKLEN(sock), pbuf, LIB_BUFLENGTH,
488b8da087Schristos 			NULL, 0, gni_flags)) {
498b8da087Schristos 		errno = saved_errno;
508585484eSchristos 		return stoa(sock);	/* use address */
518b8da087Schristos 	}
52abb0f93cSkardel 
538585484eSchristos 	TRACE(1, ("%s reversed to %s\n", stoa(sock), pbuf));
548585484eSchristos 
558585484eSchristos 	/*
568585484eSchristos 	 * Resolve the reversed name and make sure the reversed address
578585484eSchristos 	 * is among the results.
588585484eSchristos 	 */
598585484eSchristos 	ZERO(hints);
608585484eSchristos 	hints.ai_family = AF(sock);
618585484eSchristos 	hints.ai_protocol = IPPROTO_UDP;
628585484eSchristos 	hints.ai_socktype = SOCK_DGRAM;
638585484eSchristos 	hints.ai_flags = 0;
648585484eSchristos 	alist = NULL;
658585484eSchristos 
668585484eSchristos 	a_info = getaddrinfo(pbuf, svc, &hints, &alist);
678585484eSchristos 	if (a_info == EAI_NONAME
688585484eSchristos #ifdef EAI_NODATA
698585484eSchristos 	    || a_info == EAI_NODATA
708585484eSchristos #endif
718585484eSchristos 	   ) {
728585484eSchristos 		hints.ai_flags = AI_CANONNAME;
738585484eSchristos #ifdef AI_ADDRCONFIG
748585484eSchristos 		hints.ai_flags |= AI_ADDRCONFIG;
758585484eSchristos #endif
768585484eSchristos 		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
778585484eSchristos 	}
788585484eSchristos #ifdef AI_ADDRCONFIG
798585484eSchristos 	/* Some older implementations don't like AI_ADDRCONFIG. */
808585484eSchristos 	if (a_info == EAI_BADFLAGS) {
818585484eSchristos 		hints.ai_flags &= ~AI_ADDRCONFIG;
828585484eSchristos 		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
838585484eSchristos 	}
848585484eSchristos #endif
858585484eSchristos 	if (a_info)
868585484eSchristos 		goto forward_fail;
878585484eSchristos 
88af12ab5eSchristos 	INSIST(alist != NULL);
898585484eSchristos 
908585484eSchristos 	for (ai = alist; ai != NULL; ai = ai->ai_next) {
918585484eSchristos 		/*
928585484eSchristos 		 * Make a convenience sockaddr_u copy from ai->ai_addr
938585484eSchristos 		 * because casting from sockaddr * to sockaddr_u * is
948585484eSchristos 		 * risking alignment problems on platforms where
958585484eSchristos 		 * sockaddr_u has stricter alignment than sockaddr,
968585484eSchristos 		 * such as sparc.
978585484eSchristos 		 */
988585484eSchristos 		ZERO_SOCK(&addr);
998585484eSchristos 		octets = min(sizeof(addr), ai->ai_addrlen);
1008585484eSchristos 		memcpy(&addr, ai->ai_addr, octets);
1018585484eSchristos 		if (SOCK_EQ(sock, &addr))
1028585484eSchristos 			break;
1038585484eSchristos 	}
1048585484eSchristos 	freeaddrinfo(alist);
1058585484eSchristos 
1068b8da087Schristos 	if (ai != NULL) {
1078b8da087Schristos 		errno = saved_errno;
1088585484eSchristos 		return pbuf;	/* forward check passed */
1098b8da087Schristos 	}
1108585484eSchristos 
1118585484eSchristos     forward_fail:
1128585484eSchristos 	TRACE(1, ("%s forward check lookup fail: %s\n", pbuf,
1138585484eSchristos 		  gai_strerror(a_info)));
1148585484eSchristos 	LIB_GETBUF(pliar);
1158585484eSchristos 	snprintf(pliar, LIB_BUFLENGTH, "%s (%s)", stoa(sock), pbuf);
1168585484eSchristos 
1178b8da087Schristos 	errno = saved_errno;
1188585484eSchristos 	return pliar;
119abb0f93cSkardel }
120