ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/irc_getnameinfo.c
Revision: 31
Committed: Sun Oct 2 20:34:05 2005 UTC (20 years, 10 months ago) by knight
Content type: text/x-csrc
Original Path: ircd-hybrid/src/irc_getnameinfo.c
File size: 6574 byte(s)
Log Message:
- Fix svn:keywords

File Contents

# User Rev Content
1 adx 30 /*
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     #include "irc_getnameinfo.h"
47     #include "irc_string.h"
48    
49 knight 31 /* $Id$ */
50 adx 30
51     static const struct afd {
52     int a_af;
53     int a_addrlen;
54     socklen_t a_socklen;
55     int a_off;
56     } afdl [] = {
57     #ifdef IPV6
58     {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
59     offsetof(struct sockaddr_in6, sin6_addr)},
60     #endif
61     {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
62     offsetof(struct sockaddr_in, sin_addr)},
63     {0, 0, 0, 0},
64     };
65    
66     struct sockinet
67     {
68     unsigned char si_len;
69     unsigned char si_family;
70     unsigned short si_port;
71     };
72    
73     #ifdef IPV6
74     static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
75     size_t, int);
76     #endif
77    
78     int
79     irc_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
80     size_t hostlen, char *serv, size_t servlen, int flags)
81     {
82     const struct afd *afd;
83     struct servent *sp;
84     unsigned short port;
85     int family, i;
86     const char *addr;
87     u_int32_t v4a;
88     char numserv[512];
89     char numaddr[512];
90    
91     if (sa == NULL)
92     return EAI_FAIL;
93    
94     /* if (sa->sa_len != salen)
95     return EAI_FAIL;
96     */
97     family = sa->sa_family;
98     for (i = 0; afdl[i].a_af; i++)
99     if (afdl[i].a_af == family) {
100     afd = &afdl[i];
101     goto found;
102     }
103     return EAI_FAMILY;
104    
105     found:
106     if (salen != afd->a_socklen)
107     return EAI_FAIL;
108    
109     /* network byte order */
110     port = ((const struct sockinet *)sa)->si_port;
111     addr = (const char *)sa + afd->a_off;
112    
113     if (serv == NULL || servlen == 0) {
114     /*
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.
119     */
120     } else {
121     if (flags & NI_NUMERICSERV)
122     sp = NULL;
123     else {
124     sp = getservbyport(port,
125     (flags & NI_DGRAM) ? "udp" : "tcp");
126     }
127     if (sp) {
128     if (strlen(sp->s_name) + 1 > servlen)
129     return EAI_MEMORY;
130     strlcpy(serv, sp->s_name, servlen);
131     } else {
132     snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
133     if (strlen(numserv) + 1 > servlen)
134     return EAI_MEMORY;
135     strlcpy(serv, numserv, servlen);
136     }
137     }
138    
139     switch (sa->sa_family) {
140     case AF_INET:
141     v4a = (u_int32_t)
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;
146     if (v4a == 0)
147     flags |= NI_NUMERICHOST;
148     break;
149     #ifdef IPV6
150     case AF_INET6:
151     {
152     const struct sockaddr_in6 *sin6;
153     sin6 = (const struct sockaddr_in6 *)sa;
154     switch (sin6->sin6_addr.s6_addr[0]) {
155     case 0x00:
156     if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
157     ;
158     else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
159     ;
160     else
161     flags |= NI_NUMERICHOST;
162     break;
163     default:
164     if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
165     flags |= NI_NUMERICHOST;
166     }
167     else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
168     flags |= NI_NUMERICHOST;
169     break;
170     }
171     }
172     break;
173     #endif
174     }
175     if (host == NULL || hostlen == 0) {
176     /*
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.
181     */
182     } else if (flags & NI_NUMERICHOST) {
183     size_t numaddrlen;
184    
185     /* NUMERICHOST and NAMEREQD conflicts with each other */
186     if (flags & NI_NAMEREQD)
187     return EAI_NONAME;
188    
189     switch(afd->a_af) {
190     #ifdef IPV6
191     case AF_INET6:
192     {
193     int error;
194    
195     if ((error = ip6_parsenumeric(sa, addr, host,
196     hostlen, flags)) != 0)
197     return(error);
198     break;
199     }
200     #endif
201     default:
202     if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
203     == NULL)
204     return EAI_SYSTEM;
205     numaddrlen = strlen(numaddr);
206     if (numaddrlen + 1 > hostlen) /* don't forget terminator */
207     return EAI_MEMORY;
208     strlcpy(host, numaddr, hostlen);
209     break;
210     }
211     }
212     return(0);
213     }
214    
215     #ifdef IPV6
216     static int
217     ip6_parsenumeric(const struct sockaddr *sa, const char *addr,
218     char *host, size_t hostlen, int flags)
219     {
220     size_t numaddrlen;
221     char numaddr[512];
222    
223     if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
224     return(EAI_SYSTEM);
225    
226     numaddrlen = strlen(numaddr);
227    
228     if (numaddrlen + 1 > hostlen) /* don't forget terminator */
229     return(EAI_MEMORY);
230    
231     if (*numaddr == ':')
232     {
233     *host = '0';
234     strlcpy(host+1, numaddr, hostlen-1);
235     }
236     else
237     strlcpy(host, numaddr, hostlen);
238    
239     return(0);
240     }
241     #endif

Properties

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