2 * Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/lib/libutil/realhostname.c,v 1.6.2.6 2002/06/29 18:26:37 ume Exp $
27 * $DragonFly: src/lib/libutil/realhostname.c,v 1.2 2003/06/17 04:26:52 dillon Exp $
30 #include <sys/param.h>
32 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
42 /* wrapper for KAME-special getnameinfo() */
43 #ifndef NI_WITHSCOPEID
44 #define NI_WITHSCOPEID 0
54 realhostname(char *host
, size_t hsize
, const struct in_addr
*ip
)
56 char trimmed
[MAXHOSTNAMELEN
];
60 result
= HOSTNAME_INVALIDADDR
;
61 hp
= gethostbyaddr(ip
, sizeof(*ip
), AF_INET
);
64 strlcpy(trimmed
, hp
->h_name
, sizeof(trimmed
));
65 trimdomain(trimmed
, strlen(trimmed
));
66 if (strlen(trimmed
) <= hsize
) {
67 char lookup
[MAXHOSTNAMELEN
];
69 strncpy(lookup
, hp
->h_name
, sizeof(lookup
) - 1);
70 lookup
[sizeof(lookup
) - 1] = '\0';
71 hp
= gethostbyname(lookup
);
73 result
= HOSTNAME_INVALIDNAME
;
74 else for (; ; hp
->h_addr_list
++) {
75 if (*hp
->h_addr_list
== NULL
) {
76 result
= HOSTNAME_INCORRECTNAME
;
79 if (!memcmp(*hp
->h_addr_list
, ip
, sizeof(*ip
))) {
80 strncpy(host
, trimmed
, hsize
);
81 return HOSTNAME_FOUND
;
87 strncpy(host
, inet_ntoa(*ip
), hsize
);
93 realhostname_sa(char *host
, size_t hsize
, struct sockaddr
*addr
, int addrlen
)
97 struct sockaddr_in sin
;
99 result
= HOSTNAME_INVALIDADDR
;
102 /* IPv4 mapped IPv6 addr consideraton, specified in rfc2373. */
103 if (addr
->sa_family
== AF_INET6
&&
104 addrlen
== sizeof(struct sockaddr_in6
) &&
105 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6
*)addr
)->sin6_addr
)) {
106 struct sockaddr_in6
*sin6
;
108 sin6
= (struct sockaddr_in6
*)addr
;
110 memset(&sin
, 0, sizeof(sin
));
111 sin
.sin_len
= sizeof(struct sockaddr_in
);
112 sin
.sin_family
= AF_INET
;
113 sin
.sin_port
= sin6
->sin6_port
;
114 memcpy(&sin
.sin_addr
, &sin6
->sin6_addr
.s6_addr
[12],
115 sizeof(struct in_addr
));
116 addr
= (struct sockaddr
*)&sin
;
117 addrlen
= sin
.sin_len
;
121 error
= getnameinfo(addr
, addrlen
, buf
, sizeof(buf
), NULL
, 0,
122 NI_WITHSCOPEID
| NI_NAMEREQD
);
124 struct addrinfo hints
, *res
, *ores
;
127 memset(&hints
, 0, sizeof(struct addrinfo
));
128 hints
.ai_family
= addr
->sa_family
;
129 hints
.ai_flags
= AI_CANONNAME
| AI_PASSIVE
;
130 hints
.ai_socktype
= SOCK_STREAM
;
132 error
= getaddrinfo(buf
, NULL
, &hints
, &res
);
134 result
= HOSTNAME_INVALIDNAME
;
137 for (ores
= res
; ; res
= res
->ai_next
) {
140 result
= HOSTNAME_INCORRECTNAME
;
146 result
= HOSTNAME_INCORRECTNAME
;
149 if (sa
->sa_len
== addrlen
&&
150 sa
->sa_family
== addr
->sa_family
) {
151 ((struct sockinet
*)sa
)->si_port
= ((struct sockinet
*)addr
)->si_port
;
154 * XXX: sin6_socpe_id may not been
157 if (sa
->sa_family
== AF_INET6
&&
158 ((struct sockaddr_in6
*)sa
)->sin6_scope_id
== 0)
159 ((struct sockaddr_in6
*)sa
)->sin6_scope_id
= ((struct sockaddr_in6
*)addr
)->sin6_scope_id
;
161 if (!memcmp(sa
, addr
, sa
->sa_len
)) {
162 result
= HOSTNAME_FOUND
;
163 if (ores
->ai_canonname
== NULL
) {
167 strlcpy(buf
, ores
->ai_canonname
,
169 trimdomain(buf
, hsize
);
170 if (strlen(buf
) > hsize
&&
171 addr
->sa_family
== AF_INET
) {
175 strncpy(host
, buf
, hsize
);
183 if (getnameinfo(addr
, addrlen
, buf
, sizeof(buf
), NULL
, 0,
184 NI_NUMERICHOST
|NI_WITHSCOPEID
) == 0)
185 strncpy(host
, buf
, hsize
);