2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
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.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * Issues to be discussed:
32 * - Thread safe-ness must be checked
33 * - Return values. There seems to be no standard for return value (RFC2133)
34 * but INRIA implementation returns EAI_xxx defined for getaddrinfo().
38 #include <sys/types.h>
41 # include <net/socket.h>
43 # include <sys/socket.h>
45 #include <netinet/in.h>
46 #if defined(HAVE_ARPA_INET_H)
47 #include <arpa/inet.h>
49 #if defined(HAVE_ARPA_NAMESER_H)
50 #include <arpa/nameser.h>
53 #if defined(HAVE_RESOLV_H)
63 #define snprintf _snprintf
95 {PF_INET6
, sizeof(struct in6_addr
),
96 sizeof(struct sockaddr_in6
),
97 offsetof(struct sockaddr_in6
, sin6_addr
)},
102 {PF_INET
, sizeof(struct in_addr
),
103 sizeof(struct sockaddr_in
),
104 offsetof(struct sockaddr_in
, sin_addr
)},
108 #define ENI_NOSOCKET 0
109 #define ENI_NOSERVNAME 1
110 #define ENI_NOHOSTNAME 2
116 #ifndef HAVE_INET_NTOP
118 inet_ntop(af
, addr
, numaddr
, numaddr_len
)
124 #ifdef HAVE_INET_NTOA
126 memcpy(&in
.s_addr
, addr
, sizeof(in
.s_addr
));
127 snprintf(numaddr
, numaddr_len
, "%s", inet_ntoa(in
));
129 unsigned long x
= ntohl(*(unsigned long*)addr
);
130 snprintf(numaddr
, numaddr_len
, "%d.%d.%d.%d",
131 (int) (x
>>24) & 0xff, (int) (x
>>16) & 0xff,
132 (int) (x
>> 8) & 0xff, (int) (x
>> 0) & 0xff);
139 getnameinfo(sa
, salen
, host
, hostlen
, serv
, servlen
, flags
)
140 const struct sockaddr
*sa
;
166 if (len
!= salen
) return ENI_SALEN
;
168 family
= sa
->sa_family
;
169 for (i
= 0; afdl
[i
].a_af
; i
++)
170 if (afdl
[i
].a_af
== family
) {
177 if (len
!= afd
->a_socklen
) return ENI_SALEN
;
179 port
= ((struct sockinet
*)sa
)->si_port
; /* network byte order */
180 addr
= (char *)sa
+ afd
->a_off
;
182 if (serv
== NULL
|| servlen
== 0) {
183 /* what we should do? */
184 } else if (flags
& NI_NUMERICSERV
) {
185 snprintf(numserv
, sizeof(numserv
), "%d", ntohs(port
));
186 if (strlen(numserv
) + 1 > servlen
)
188 strcpy(serv
, numserv
);
190 #if defined(HAVE_GETSERVBYPORT)
191 sp
= getservbyport(port
, (flags
& NI_DGRAM
) ? "udp" : "tcp");
193 if (strlen(sp
->s_name
) + 1 > servlen
)
195 strcpy(serv
, sp
->s_name
);
197 return ENI_NOSERVNAME
;
199 return ENI_NOSERVNAME
;
203 switch (sa
->sa_family
) {
205 v4a
= ntohl(((struct sockaddr_in
*)sa
)->sin_addr
.s_addr
);
206 if (IN_MULTICAST(v4a
) || IN_EXPERIMENTAL(v4a
))
207 flags
|= NI_NUMERICHOST
;
208 v4a
>>= IN_CLASSA_NSHIFT
;
210 flags
|= NI_NUMERICHOST
;
215 pfx
= ((struct sockaddr_in6
*)sa
)->sin6_addr
.s6_addr8
[0];
217 pfx
= ((struct sockaddr_in6
*)sa
)->sin6_addr
.s6_addr
[0];
219 if (pfx
== 0 || pfx
== 0xfe || pfx
== 0xff)
220 flags
|= NI_NUMERICHOST
;
224 if (host
== NULL
|| hostlen
== 0) {
225 /* what should we do? */
226 } else if (flags
& NI_NUMERICHOST
) {
227 if (inet_ntop(afd
->a_af
, addr
, numaddr
, sizeof(numaddr
))
230 if (strlen(numaddr
) > hostlen
)
232 strcpy(host
, numaddr
);
235 hp
= getipnodebyaddr(addr
, afd
->a_addrlen
, afd
->a_af
, &h_error
);
237 hp
= gethostbyaddr(addr
, afd
->a_addrlen
, afd
->a_af
);
242 if (flags
& NI_NOFQDN
) {
243 p
= strchr(hp
->h_name
, '.');
246 if (strlen(hp
->h_name
) + 1 > hostlen
) {
252 strcpy(host
, hp
->h_name
);
257 if (flags
& NI_NAMEREQD
)
258 return ENI_NOHOSTNAME
;
259 if (inet_ntop(afd
->a_af
, addr
, numaddr
, sizeof(numaddr
))
261 return ENI_NOHOSTNAME
;
262 if (strlen(numaddr
) > hostlen
)
264 strcpy(host
, numaddr
);