~ubuntu-branches/ubuntu/hardy/ruby1.8/hardy-updates

« back to all changes in this revision

Viewing changes to ext/socket/getnameinfo.c

  • Committer: Bazaar Package Importer
  • Author(s): akira yamada
  • Date: 2007-03-13 22:11:58 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20070313221158-h3oql37brlaf2go2
Tags: 1.8.6-1
* new upstream version, 1.8.6.
* libruby1.8 conflicts with libopenssl-ruby1.8 (< 1.8.6) (closes: #410018)
* changed packaging style to cdbs from dbs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 * - Return values.  There seems to be no standard for return value (RFC2133)
 
34
 *   but INRIA implementation returns EAI_xxx defined for getaddrinfo().
 
35
 */
 
36
 
 
37
#include "config.h"
 
38
#include <sys/types.h>
 
39
#ifndef _WIN32
 
40
#if defined(__BEOS__)
 
41
# include <net/socket.h>
 
42
#else
 
43
# include <sys/socket.h>
 
44
#endif
 
45
#include <netinet/in.h>
 
46
#if defined(HAVE_ARPA_INET_H)
 
47
#include <arpa/inet.h>
 
48
#endif
 
49
#if defined(HAVE_ARPA_NAMESER_H)
 
50
#include <arpa/nameser.h>
 
51
#endif
 
52
#include <netdb.h>
 
53
#if defined(HAVE_RESOLV_H)
 
54
#ifdef _SX
 
55
#include <stdio.h>
 
56
#endif
 
57
#include <resolv.h>
 
58
#endif
 
59
#endif
 
60
#ifdef _WIN32
 
61
#include <winsock2.h>
 
62
#include <stdio.h>
 
63
#define snprintf _snprintf
 
64
#endif
 
65
 
 
66
#include <string.h>
 
67
#include <stddef.h>
 
68
 
 
69
#ifdef SOCKS5
 
70
#include <socks.h>
 
71
#endif
 
72
 
 
73
#include "addrinfo.h"
 
74
#include "sockport.h"
 
75
 
 
76
#define SUCCESS 0
 
77
#define ANY 0
 
78
#define YES 1
 
79
#define NO  0
 
80
 
 
81
struct sockinet {
 
82
        u_char  si_len;
 
83
        u_char  si_family;
 
84
        u_short si_port;
 
85
};
 
86
 
 
87
static struct afd {
 
88
        int a_af;
 
89
        int a_addrlen;
 
90
        int a_socklen;
 
91
        int a_off;
 
92
} afdl [] = {
 
93
#ifdef INET6
 
94
#define N_INET6 0
 
95
        {PF_INET6, sizeof(struct in6_addr),
 
96
         sizeof(struct sockaddr_in6),
 
97
         offsetof(struct sockaddr_in6, sin6_addr)},
 
98
#define N_INET  1
 
99
#else
 
100
#define N_INET  0
 
101
#endif
 
102
        {PF_INET, sizeof(struct in_addr),
 
103
         sizeof(struct sockaddr_in),
 
104
         offsetof(struct sockaddr_in, sin_addr)},
 
105
        {0, 0, 0, 0},
 
106
};
 
107
 
 
108
#define ENI_NOSOCKET    0
 
109
#define ENI_NOSERVNAME  1
 
110
#define ENI_NOHOSTNAME  2
 
111
#define ENI_MEMORY      3
 
112
#define ENI_SYSTEM      4
 
113
#define ENI_FAMILY      5
 
114
#define ENI_SALEN       6
 
115
 
 
116
#ifndef HAVE_INET_NTOP
 
117
static const char *
 
118
inet_ntop(af, addr, numaddr, numaddr_len)
 
119
        int af;
 
120
        const void *addr;
 
121
        char *numaddr;
 
122
        size_t numaddr_len;
 
123
{
 
124
#ifdef HAVE_INET_NTOA
 
125
        struct in_addr in;
 
126
        memcpy(&in.s_addr, addr, sizeof(in.s_addr));
 
127
        snprintf(numaddr, numaddr_len, "%s", inet_ntoa(in));
 
128
#else
 
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);
 
133
#endif
 
134
        return numaddr;
 
135
}
 
136
#endif
 
137
 
 
138
int
 
139
getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
 
140
        const struct sockaddr *sa;
 
141
        size_t salen;
 
142
        char *host;
 
143
        size_t hostlen;
 
144
        char *serv;
 
145
        size_t servlen;
 
146
        int flags;
 
147
{
 
148
        struct afd *afd;
 
149
        struct servent *sp;
 
150
        struct hostent *hp;
 
151
        u_short port;
 
152
        int family, len, i;
 
153
        char *addr, *p;
 
154
        u_long v4a;
 
155
#ifdef INET6
 
156
        u_char pfx;
 
157
#endif
 
158
        int h_error;
 
159
        char numserv[512];
 
160
        char numaddr[512];
 
161
 
 
162
        if (sa == NULL)
 
163
                return ENI_NOSOCKET;
 
164
 
 
165
        len = SA_LEN(sa);
 
166
        if (len != salen) return ENI_SALEN;
 
167
        
 
168
        family = sa->sa_family;
 
169
        for (i = 0; afdl[i].a_af; i++)
 
170
                if (afdl[i].a_af == family) {
 
171
                        afd = &afdl[i];
 
172
                        goto found;
 
173
                }
 
174
        return ENI_FAMILY;
 
175
        
 
176
 found:
 
177
        if (len != afd->a_socklen) return ENI_SALEN;
 
178
        
 
179
        port = ((struct sockinet *)sa)->si_port; /* network byte order */
 
180
        addr = (char *)sa + afd->a_off;
 
181
 
 
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)
 
187
                        return ENI_MEMORY;
 
188
                strcpy(serv, numserv);
 
189
        } else {
 
190
#if defined(HAVE_GETSERVBYPORT)
 
191
                sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
 
192
                if (sp) {
 
193
                        if (strlen(sp->s_name) + 1 > servlen)
 
194
                                return ENI_MEMORY;
 
195
                        strcpy(serv, sp->s_name);
 
196
                } else
 
197
                        return ENI_NOSERVNAME;
 
198
#else
 
199
                return ENI_NOSERVNAME;
 
200
#endif
 
201
        }
 
202
 
 
203
        switch (sa->sa_family) {
 
204
        case AF_INET:
 
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;
 
209
                if (v4a == 0)
 
210
                        flags |= NI_NUMERICHOST;                        
 
211
                break;
 
212
#ifdef INET6
 
213
        case AF_INET6:
 
214
#ifdef HAVE_ADDR8
 
215
                pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0];
 
216
#else
 
217
                pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0];
 
218
#endif
 
219
                if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
 
220
                        flags |= NI_NUMERICHOST;
 
221
                break;
 
222
#endif
 
223
        }
 
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))
 
228
                    == NULL)
 
229
                        return ENI_SYSTEM;
 
230
                if (strlen(numaddr) > hostlen)
 
231
                        return ENI_MEMORY;
 
232
                strcpy(host, numaddr);
 
233
        } else {
 
234
#ifdef INET6
 
235
                hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
 
236
#else
 
237
                hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
 
238
                h_error = h_errno;
 
239
#endif
 
240
 
 
241
                if (hp) {
 
242
                        if (flags & NI_NOFQDN) {
 
243
                                p = strchr(hp->h_name, '.');
 
244
                                if (p) *p = '\0';
 
245
                        }
 
246
                        if (strlen(hp->h_name) + 1 > hostlen) {
 
247
#ifdef INET6
 
248
                                freehostent(hp);
 
249
#endif
 
250
                                return ENI_MEMORY;
 
251
                        }
 
252
                        strcpy(host, hp->h_name);
 
253
#ifdef INET6
 
254
                        freehostent(hp);
 
255
#endif
 
256
                } else {
 
257
                        if (flags & NI_NAMEREQD)
 
258
                                return ENI_NOHOSTNAME;
 
259
                        if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
 
260
                            == NULL)
 
261
                                return ENI_NOHOSTNAME;
 
262
                        if (strlen(numaddr) > hostlen)
 
263
                                return ENI_MEMORY;
 
264
                        strcpy(host, numaddr);
 
265
                }
 
266
        }
 
267
        return SUCCESS;
 
268
}