]>
jfr.im git - solanum.git/blob - authd/getnameinfo.c
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 * - RFC2553 says that we should raise error on short buffer. X/Open says
34 * we need to truncate the result. We obey RFC2553 (and X/Open should be
35 * modified). ipngwg rough consensus seems to follow RFC2553.
36 * - What is "local" in NI_FQDN?
37 * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other.
38 * - (KAME extension) always attach textual scopeid (fe80::1%lo0), if
39 * sin6_scope_id is filled - standardization status?
40 * XXX breaks backward compat for code that expects no scopeid.
46 #include "getaddrinfo.h"
47 #include "getnameinfo.h"
49 static const struct afd
{
52 rb_socklen_t a_socklen
;
56 {PF_INET6
, sizeof(struct in6_addr
), sizeof(struct sockaddr_in6
),
57 offsetof(struct sockaddr_in6
, sin6_addr
)},
59 {PF_INET
, sizeof(struct in_addr
), sizeof(struct sockaddr_in
),
60 offsetof(struct sockaddr_in
, sin_addr
)},
67 unsigned char si_family
;
68 unsigned short si_port
;
72 static int ip6_parsenumeric(const struct sockaddr
*, const char *, char *,
77 rb_getnameinfo(const struct sockaddr
*sa
, rb_socklen_t salen
, char *host
,
78 size_t hostlen
, char *serv
, size_t servlen
, int flags
)
80 const struct afd
*afd
;
92 /* if (sa->sa_len != salen)
95 family
= sa
->sa_family
;
96 for (i
= 0; afdl
[i
].a_af
; i
++)
97 if (afdl
[i
].a_af
== family
) {
104 if (salen
!= afd
->a_socklen
)
107 /* network byte order */
108 port
= ((const struct sockinet
*)sa
)->si_port
;
109 addr
= (const char *)sa
+ afd
->a_off
;
111 if (serv
== NULL
|| servlen
== 0) {
113 * do nothing in this case.
114 * in case you are wondering if "&&" is more correct than
115 * "||" here: rfc2553bis-03 says that serv == NULL OR
116 * servlen == 0 means that the caller does not want the result.
119 if (flags
& NI_NUMERICSERV
)
122 sp
= getservbyport(port
,
123 (flags
& NI_DGRAM
) ? "udp" : "tcp");
126 if (strlen(sp
->s_name
) + 1 > servlen
)
128 rb_strlcpy(serv
, sp
->s_name
, servlen
);
130 snprintf(numserv
, sizeof(numserv
), "%u", ntohs(port
));
131 if (strlen(numserv
) + 1 > servlen
)
133 rb_strlcpy(serv
, numserv
, servlen
);
137 switch (sa
->sa_family
) {
140 ntohl(((const struct sockaddr_in
*)sa
)->sin_addr
.s_addr
);
141 if (IN_MULTICAST(v4a
) || IN_EXPERIMENTAL(v4a
))
142 flags
|= NI_NUMERICHOST
;
143 v4a
>>= IN_CLASSA_NSHIFT
;
145 flags
|= NI_NUMERICHOST
;
150 const struct sockaddr_in6
*sin6
;
151 sin6
= (const struct sockaddr_in6
*)sa
;
152 switch (sin6
->sin6_addr
.s6_addr
[0]) {
154 if (IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
))
156 else if (IN6_IS_ADDR_LOOPBACK(&sin6
->sin6_addr
))
159 flags
|= NI_NUMERICHOST
;
162 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
)) {
163 flags
|= NI_NUMERICHOST
;
165 else if (IN6_IS_ADDR_MULTICAST(&sin6
->sin6_addr
))
166 flags
|= NI_NUMERICHOST
;
173 if (host
== NULL
|| hostlen
== 0) {
175 * do nothing in this case.
176 * in case you are wondering if "&&" is more correct than
177 * "||" here: rfc2553bis-03 says that host == NULL or
178 * hostlen == 0 means that the caller does not want the result.
180 } else if (flags
& NI_NUMERICHOST
) {
183 /* NUMERICHOST and NAMEREQD conflicts with each other */
184 if (flags
& NI_NAMEREQD
)
193 if ((error
= ip6_parsenumeric(sa
, addr
, host
,
194 hostlen
, flags
)) != 0)
200 if (rb_inet_ntop(afd
->a_af
, addr
, numaddr
, sizeof(numaddr
))
203 numaddrlen
= strlen(numaddr
);
204 if (numaddrlen
+ 1 > hostlen
) /* don't forget terminator */
206 rb_strlcpy(host
, numaddr
, hostlen
);
215 ip6_parsenumeric(const struct sockaddr
*sa
, const char *addr
,
216 char *host
, size_t hostlen
, int flags
)
221 if (rb_inet_ntop(AF_INET6
, addr
, numaddr
, sizeof(numaddr
)) == NULL
)
224 numaddrlen
= strlen(numaddr
);
226 if (numaddrlen
+ 1 > hostlen
) /* don't forget terminator */
232 rb_strlcpy(host
+1, numaddr
, hostlen
-1);
235 rb_strlcpy(host
, numaddr
, hostlen
);