ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/branches/ircd-hybrid-newconf/libio/net/irc_getnameinfo.c
Revision: 1027
Committed: Sun Nov 8 13:01:13 2009 UTC (16 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 6520 byte(s)
Log Message:
- Move old 7.3 sources to branches/ircd-hybrid-newconf

File Contents

# Content
1 /*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
16 *
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
27 * SUCH DAMAGE.
28 */
29
30 /*
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.
41 * beware on merge.
42 */
43
44 #include "stdinc.h"
45
46 /* $Id$ */
47
48 static const struct afd {
49 int a_af;
50 int a_addrlen;
51 socklen_t a_socklen;
52 int a_off;
53 } afdl [] = {
54 #ifdef IPV6
55 {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
56 offsetof(struct sockaddr_in6, sin6_addr)},
57 #endif
58 {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
59 offsetof(struct sockaddr_in, sin_addr)},
60 {0, 0, 0, 0},
61 };
62
63 struct sockinet
64 {
65 unsigned char si_len;
66 unsigned char si_family;
67 unsigned short si_port;
68 };
69
70 #ifdef IPV6
71 static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
72 size_t, int);
73 #endif
74
75 int
76 irc_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
77 size_t hostlen, char *serv, size_t servlen, int flags)
78 {
79 const struct afd *afd;
80 struct servent *sp;
81 unsigned short port;
82 int family, i;
83 const char *addr;
84 u_int32_t v4a;
85 char numserv[512];
86 char numaddr[512];
87
88 if (sa == NULL)
89 return EAI_FAIL;
90
91 /* if (sa->sa_len != salen)
92 return EAI_FAIL;
93 */
94 family = sa->sa_family;
95 for (i = 0; afdl[i].a_af; i++)
96 if (afdl[i].a_af == family) {
97 afd = &afdl[i];
98 goto found;
99 }
100 return EAI_FAMILY;
101
102 found:
103 if (salen != afd->a_socklen)
104 return EAI_FAIL;
105
106 /* network byte order */
107 port = ((const struct sockinet *)sa)->si_port;
108 addr = (const char *)sa + afd->a_off;
109
110 if (serv == NULL || servlen == 0) {
111 /*
112 * do nothing in this case.
113 * in case you are wondering if "&&" is more correct than
114 * "||" here: rfc2553bis-03 says that serv == NULL OR
115 * servlen == 0 means that the caller does not want the result.
116 */
117 } else {
118 if (flags & NI_NUMERICSERV)
119 sp = NULL;
120 else {
121 sp = getservbyport(port,
122 (flags & NI_DGRAM) ? "udp" : "tcp");
123 }
124 if (sp) {
125 if (strlen(sp->s_name) + 1 > servlen)
126 return EAI_MEMORY;
127 strlcpy(serv, sp->s_name, servlen);
128 } else {
129 snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
130 if (strlen(numserv) + 1 > servlen)
131 return EAI_MEMORY;
132 strlcpy(serv, numserv, servlen);
133 }
134 }
135
136 switch (sa->sa_family) {
137 case AF_INET:
138 v4a = (u_int32_t)
139 ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
140 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
141 flags |= NI_NUMERICHOST;
142 v4a >>= IN_CLASSA_NSHIFT;
143 if (v4a == 0)
144 flags |= NI_NUMERICHOST;
145 break;
146 #ifdef IPV6
147 case AF_INET6:
148 {
149 const struct sockaddr_in6 *sin6;
150 sin6 = (const struct sockaddr_in6 *)sa;
151 switch (sin6->sin6_addr.s6_addr[0]) {
152 case 0x00:
153 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
154 ;
155 else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
156 ;
157 else
158 flags |= NI_NUMERICHOST;
159 break;
160 default:
161 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
162 flags |= NI_NUMERICHOST;
163 }
164 else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
165 flags |= NI_NUMERICHOST;
166 break;
167 }
168 }
169 break;
170 #endif
171 }
172 if (host == NULL || hostlen == 0) {
173 /*
174 * do nothing in this case.
175 * in case you are wondering if "&&" is more correct than
176 * "||" here: rfc2553bis-03 says that host == NULL or
177 * hostlen == 0 means that the caller does not want the result.
178 */
179 } else if (flags & NI_NUMERICHOST) {
180 size_t numaddrlen;
181
182 /* NUMERICHOST and NAMEREQD conflicts with each other */
183 if (flags & NI_NAMEREQD)
184 return EAI_NONAME;
185
186 switch(afd->a_af) {
187 #ifdef IPV6
188 case AF_INET6:
189 {
190 int error;
191
192 if ((error = ip6_parsenumeric(sa, addr, host,
193 hostlen, flags)) != 0)
194 return(error);
195 break;
196 }
197 #endif
198 default:
199 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
200 == NULL)
201 return EAI_SYSTEM;
202 numaddrlen = strlen(numaddr);
203 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
204 return EAI_MEMORY;
205 strlcpy(host, numaddr, hostlen);
206 break;
207 }
208 }
209 return(0);
210 }
211
212 #ifdef IPV6
213 static int
214 ip6_parsenumeric(const struct sockaddr *sa, const char *addr,
215 char *host, size_t hostlen, int flags)
216 {
217 size_t numaddrlen;
218 char numaddr[512];
219
220 if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
221 return(EAI_SYSTEM);
222
223 numaddrlen = strlen(numaddr);
224
225 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
226 return(EAI_MEMORY);
227
228 if (*numaddr == ':')
229 {
230 *host = '0';
231 strlcpy(host+1, numaddr, hostlen-1);
232 }
233 else
234 strlcpy(host, numaddr, hostlen);
235
236 return(0);
237 }
238 #endif

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision