]>
git.saurik.com Git - apple/libutil.git/blob - realhostname.c
57bc6513e3b9a9d81511aeb43908e564f1605819
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
27 #include <sys/cdefs.h>
29 #include <sys/param.h>
30 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
48 realhostname(char *host
, size_t hsize
, const struct in_addr
*ip
)
50 char trimmed
[MAXHOSTNAMELEN
];
54 result
= HOSTNAME_INVALIDADDR
;
55 hp
= gethostbyaddr((const char *)ip
, sizeof(*ip
), AF_INET
);
58 strlcpy(trimmed
, hp
->h_name
, sizeof(trimmed
));
59 trimdomain(trimmed
, strlen(trimmed
));
60 if (strlen(trimmed
) <= hsize
) {
61 char lookup
[MAXHOSTNAMELEN
];
63 strncpy(lookup
, hp
->h_name
, sizeof(lookup
) - 1);
64 lookup
[sizeof(lookup
) - 1] = '\0';
65 hp
= gethostbyname(lookup
);
67 result
= HOSTNAME_INVALIDNAME
;
68 else for (; ; hp
->h_addr_list
++) {
69 if (*hp
->h_addr_list
== NULL
) {
70 result
= HOSTNAME_INCORRECTNAME
;
73 if (!memcmp(*hp
->h_addr_list
, ip
, sizeof(*ip
))) {
74 strncpy(host
, trimmed
, hsize
);
75 return HOSTNAME_FOUND
;
81 strncpy(host
, inet_ntoa(*ip
), hsize
);
87 realhostname_sa(char *host
, size_t hsize
, struct sockaddr
*addr
, int addrlen
)
92 result
= HOSTNAME_INVALIDADDR
;
95 /* IPv4 mapped IPv6 addr consideraton, specified in rfc2373. */
96 if (addr
->sa_family
== AF_INET6
&&
97 addrlen
== sizeof(struct sockaddr_in6
) &&
98 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6
*)addr
)->sin6_addr
)) {
99 struct sockaddr_in6
*sin6
;
101 sin6
= (struct sockaddr_in6
*)addr
;
103 memset(&lsin
, 0, sizeof(lsin
));
104 lsin
.sin_len
= sizeof(struct sockaddr_in
);
105 lsin
.sin_family
= AF_INET
;
106 lsin
.sin_port
= sin6
->sin6_port
;
107 memcpy(&lsin
.sin_addr
, &sin6
->sin6_addr
.s6_addr
[12],
108 sizeof(struct in_addr
));
109 addr
= (struct sockaddr
*)&lsin
;
110 addrlen
= lsin
.sin_len
;
114 error
= getnameinfo(addr
, addrlen
, buf
, sizeof(buf
), NULL
, 0,
117 struct addrinfo hints
, *res
, *ores
;
120 memset(&hints
, 0, sizeof(struct addrinfo
));
121 hints
.ai_family
= addr
->sa_family
;
122 hints
.ai_flags
= AI_CANONNAME
| AI_PASSIVE
;
123 hints
.ai_socktype
= SOCK_STREAM
;
125 error
= getaddrinfo(buf
, NULL
, &hints
, &res
);
127 result
= HOSTNAME_INVALIDNAME
;
130 for (ores
= res
; ; res
= res
->ai_next
) {
133 result
= HOSTNAME_INCORRECTNAME
;
139 result
= HOSTNAME_INCORRECTNAME
;
142 if (sa
->sa_len
== addrlen
&&
143 sa
->sa_family
== addr
->sa_family
) {
144 ((struct sockinet
*)sa
)->si_port
= ((struct sockinet
*)addr
)->si_port
;
147 * XXX: sin6_socpe_id may not been
150 if (sa
->sa_family
== AF_INET6
&&
151 ((struct sockaddr_in6
*)sa
)->sin6_scope_id
== 0)
152 ((struct sockaddr_in6
*)sa
)->sin6_scope_id
= ((struct sockaddr_in6
*)addr
)->sin6_scope_id
;
154 if (!memcmp(sa
, addr
, sa
->sa_len
)) {
155 result
= HOSTNAME_FOUND
;
156 if (ores
->ai_canonname
== NULL
) {
160 strlcpy(buf
, ores
->ai_canonname
,
162 trimdomain(buf
, hsize
);
163 if (strlen(buf
) > hsize
&&
164 addr
->sa_family
== AF_INET
) {
168 strncpy(host
, buf
, hsize
);
176 if (getnameinfo(addr
, addrlen
, buf
, sizeof(buf
), NULL
, 0,
177 NI_NUMERICHOST
) == 0)
178 strncpy(host
, buf
, hsize
);