]>
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.
45 #include <ratbox_lib.h>
46 #include "getaddrinfo.h"
47 #include "getnameinfo.h"
51 static const struct afd
{
54 rb_socklen_t a_socklen
;
58 {PF_INET6
, sizeof(struct in6_addr
), sizeof(struct sockaddr_in6
),
59 offsetof(struct sockaddr_in6
, sin6_addr
)},
61 {PF_INET
, sizeof(struct in_addr
), sizeof(struct sockaddr_in
),
62 offsetof(struct sockaddr_in
, sin_addr
)},
69 unsigned char si_family
;
70 unsigned short si_port
;
74 static int ip6_parsenumeric(const struct sockaddr
*, const char *, char *,
79 rb_getnameinfo(const struct sockaddr
*sa
, rb_socklen_t salen
, char *host
,
80 size_t hostlen
, char *serv
, size_t servlen
, int flags
)
82 const struct afd
*afd
;
94 /* if (sa->sa_len != salen)
97 family
= sa
->sa_family
;
98 for (i
= 0; afdl
[i
].a_af
; i
++)
99 if (afdl
[i
].a_af
== family
) {
106 if (salen
!= afd
->a_socklen
)
109 /* network byte order */
110 port
= ((const struct sockinet
*)sa
)->si_port
;
111 addr
= (const char *)sa
+ afd
->a_off
;
113 if (serv
== NULL
|| servlen
== 0) {
115 * do nothing in this case.
116 * in case you are wondering if "&&" is more correct than
117 * "||" here: rfc2553bis-03 says that serv == NULL OR
118 * servlen == 0 means that the caller does not want the result.
121 if (flags
& NI_NUMERICSERV
)
124 sp
= getservbyport(port
,
125 (flags
& NI_DGRAM
) ? "udp" : "tcp");
128 if (strlen(sp
->s_name
) + 1 > servlen
)
130 rb_strlcpy(serv
, sp
->s_name
, servlen
);
132 snprintf(numserv
, sizeof(numserv
), "%u", ntohs(port
));
133 if (strlen(numserv
) + 1 > servlen
)
135 rb_strlcpy(serv
, numserv
, servlen
);
139 switch (sa
->sa_family
) {
142 ntohl(((const struct sockaddr_in
*)sa
)->sin_addr
.s_addr
);
143 if (IN_MULTICAST(v4a
) || IN_EXPERIMENTAL(v4a
))
144 flags
|= NI_NUMERICHOST
;
145 v4a
>>= IN_CLASSA_NSHIFT
;
147 flags
|= NI_NUMERICHOST
;
152 const struct sockaddr_in6
*sin6
;
153 sin6
= (const struct sockaddr_in6
*)sa
;
154 switch (sin6
->sin6_addr
.s6_addr
[0]) {
156 if (IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
))
158 else if (IN6_IS_ADDR_LOOPBACK(&sin6
->sin6_addr
))
161 flags
|= NI_NUMERICHOST
;
164 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
)) {
165 flags
|= NI_NUMERICHOST
;
167 else if (IN6_IS_ADDR_MULTICAST(&sin6
->sin6_addr
))
168 flags
|= NI_NUMERICHOST
;
175 if (host
== NULL
|| hostlen
== 0) {
177 * do nothing in this case.
178 * in case you are wondering if "&&" is more correct than
179 * "||" here: rfc2553bis-03 says that host == NULL or
180 * hostlen == 0 means that the caller does not want the result.
182 } else if (flags
& NI_NUMERICHOST
) {
185 /* NUMERICHOST and NAMEREQD conflicts with each other */
186 if (flags
& NI_NAMEREQD
)
195 if ((error
= ip6_parsenumeric(sa
, addr
, host
,
196 hostlen
, flags
)) != 0)
202 if (rb_inet_ntop(afd
->a_af
, addr
, numaddr
, sizeof(numaddr
))
205 numaddrlen
= strlen(numaddr
);
206 if (numaddrlen
+ 1 > hostlen
) /* don't forget terminator */
208 rb_strlcpy(host
, numaddr
, hostlen
);
217 ip6_parsenumeric(const struct sockaddr
*sa
, const char *addr
,
218 char *host
, size_t hostlen
, int flags
)
223 if (rb_inet_ntop(AF_INET6
, addr
, numaddr
, sizeof(numaddr
)) == NULL
)
226 numaddrlen
= strlen(numaddr
);
228 if (numaddrlen
+ 1 > hostlen
) /* don't forget terminator */
234 rb_strlcpy(host
+1, numaddr
, hostlen
-1);
237 rb_strlcpy(host
, numaddr
, hostlen
);