Ruby 2.0.0p353(2013-11-22revision43784)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

getnameinfo.c
Go to the documentation of this file.
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 "ruby/config.h"
38 #ifdef RUBY_EXTCONF_H
39 #include RUBY_EXTCONF_H
40 #endif
41 #include <stdio.h>
42 #include <sys/types.h>
43 #ifndef _WIN32
44 #if defined(__BEOS__) && !defined(__HAIKU__) && !defined(BONE)
45 # include <net/socket.h>
46 #else
47 # include <sys/socket.h>
48 #endif
49 #include <netinet/in.h>
50 #if defined(HAVE_ARPA_INET_H)
51 #include <arpa/inet.h>
52 #endif
53 #if defined(HAVE_ARPA_NAMESER_H)
54 #include <arpa/nameser.h>
55 #endif
56 #include <netdb.h>
57 #if defined(HAVE_RESOLV_H)
58 #include <resolv.h>
59 #endif
60 #endif
61 #ifdef _WIN32
62 #include <winsock2.h>
63 #include <ws2tcpip.h>
64 #define snprintf _snprintf
65 #endif
66
67 #include <string.h>
68 #include <stddef.h>
69
70 #ifdef SOCKS5
71 #include <socks.h>
72 #endif
73
74 #include "addrinfo.h"
75 #include "sockport.h"
76
77 #define SUCCESS 0
78 #define ANY 0
79 #define YES 1
80 #define NO 0
81
82 struct sockinet {
83 u_char si_len;
84 u_char si_family;
85 u_short si_port;
86 };
87
88 static struct afd {
89 int a_af;
90 int a_addrlen;
91 int a_socklen;
92 int a_off;
93 } afdl [] = {
94 #ifdef INET6
95 #define N_INET6 0
96 {PF_INET6, sizeof(struct in6_addr),
97 sizeof(struct sockaddr_in6),
98 offsetof(struct sockaddr_in6, sin6_addr)},
99 #define N_INET 1
100 #else
101 #define N_INET 0
102 #endif
103 {PF_INET, sizeof(struct in_addr),
104 sizeof(struct sockaddr_in),
105 offsetof(struct sockaddr_in, sin_addr)},
106 {0, 0, 0, 0},
107 };
108
109 #define ENI_NOSOCKET 0
110 #define ENI_NOSERVNAME 1
111 #define ENI_NOHOSTNAME 2
112 #define ENI_MEMORY 3
113 #define ENI_SYSTEM 4
114 #define ENI_FAMILY 5
115 #define ENI_SALEN 6
116
117 #ifndef HAVE_INET_NTOP
118 static const char *
119 inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len)
120 {
121 #ifdef HAVE_INET_NTOA
122 struct in_addr in;
123 memcpy(&in.s_addr, addr, sizeof(in.s_addr));
124 snprintf(numaddr, numaddr_len, "%s", inet_ntoa(in));
125 #else
126 unsigned long x = ntohl(*(unsigned long*)addr);
127 snprintf(numaddr, numaddr_len, "%d.%d.%d.%d",
128 (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
129 (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
130 #endif
131 return numaddr;
132 }
133 #endif
134
135 int
136 getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags)
137 {
138 struct afd *afd;
139 struct hostent *hp;
140 u_short port;
141 int family, len, i;
142 char *addr, *p;
143 u_long v4a;
144 #ifdef INET6
145 u_char pfx;
146 #endif
147 int h_error;
148 char numserv[512];
149 char numaddr[512];
150
151 if (sa == NULL)
152 return ENI_NOSOCKET;
153
154 len = SA_LEN(sa);
155 if (len != salen) return ENI_SALEN;
156
157 family = sa->sa_family;
158 for (i = 0; afdl[i].a_af; i++)
159 if (afdl[i].a_af == family) {
160 afd = &afdl[i];
161 goto found;
162 }
163 return ENI_FAMILY;
164
165 found:
166 if (len != afd->a_socklen) return ENI_SALEN;
167
168 port = ((struct sockinet *)sa)->si_port; /* network byte order */
169 addr = (char *)sa + afd->a_off;
170
171 if (serv == NULL || servlen == 0) {
172 /* what we should do? */
173 } else if (flags & NI_NUMERICSERV) {
174 snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
175 if (strlen(numserv) + 1 > servlen)
176 return ENI_MEMORY;
177 strcpy(serv, numserv);
178 } else {
179 #if defined(HAVE_GETSERVBYPORT)
180 struct servent *sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
181 if (sp) {
182 if (strlen(sp->s_name) + 1 > servlen)
183 return ENI_MEMORY;
184 strcpy(serv, sp->s_name);
185 } else
186 return ENI_NOSERVNAME;
187 #else
188 return ENI_NOSERVNAME;
189 #endif
190 }
191
192 switch (sa->sa_family) {
193 case AF_INET:
194 v4a = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
195 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
196 flags |= NI_NUMERICHOST;
197 v4a >>= IN_CLASSA_NSHIFT;
198 if (v4a == 0)
199 flags |= NI_NUMERICHOST;
200 break;
201 #ifdef INET6
202 case AF_INET6:
203 #ifdef HAVE_ADDR8
204 pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0];
205 #else
206 pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0];
207 #endif
208 if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
209 flags |= NI_NUMERICHOST;
210 break;
211 #endif
212 }
213 if (host == NULL || hostlen == 0) {
214 /* what should we do? */
215 } else if (flags & NI_NUMERICHOST) {
216 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
217 == NULL)
218 return ENI_SYSTEM;
219 if (strlen(numaddr) > hostlen)
220 return ENI_MEMORY;
221 strcpy(host, numaddr);
222 } else {
223 #ifdef INET6
224 hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
225 #else
226 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
227 h_error = h_errno;
228 #endif
229
230 if (hp) {
231 if (flags & NI_NOFQDN) {
232 p = strchr(hp->h_name, '.');
233 if (p) *p = '\0';
234 }
235 if (strlen(hp->h_name) + 1 > hostlen) {
236 #ifdef INET6
237 freehostent(hp);
238 #endif
239 return ENI_MEMORY;
240 }
241 strcpy(host, hp->h_name);
242 #ifdef INET6
243 freehostent(hp);
244 #endif
245 } else {
246 if (flags & NI_NAMEREQD)
247 return ENI_NOHOSTNAME;
248 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
249 == NULL)
250 return ENI_NOHOSTNAME;
251 if (strlen(numaddr) > hostlen)
252 return ENI_MEMORY;
253 strcpy(host, numaddr);
254 }
255 }
256 return SUCCESS;
257 }
afd::a_af
int a_af
Definition: getaddrinfo.c:112
SUCCESS
#define SUCCESS
Definition: getnameinfo.c:77
addrinfo.h
strlen
size_t strlen(const char *)
PF_INET
#define PF_INET
Definition: sockport.h:77
p
Win32OLEIDispatch * p
Definition: win32ole.c:786
sockinet::si_family
u_char si_family
Definition: getaddrinfo.c:107
SA_LEN
#define SA_LEN(sa)
Definition: sockport.h:29
NI_DGRAM
#define NI_DGRAM
Definition: addrinfo.h:128
i
ssize_t i
Definition: bigdecimal.c:5655
afd::a_socklen
int a_socklen
Definition: getaddrinfo.c:114
freehostent
#define freehostent
Definition: addrinfo.h:153
sockinet
Definition: getaddrinfo.c:105
ENI_MEMORY
#define ENI_MEMORY
Definition: getnameinfo.c:112
strcpy
strcpy(cmd2, cmd)
afdl
static struct afd afdl[]
flags
int flags
Definition: tcltklib.c:3023
NI_NUMERICSERV
#define NI_NUMERICSERV
Definition: addrinfo.h:127
offsetof
#define offsetof(p_type, field)
Definition: addrinfo.h:186
inet_ntop
static const char * inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len)
Definition: getnameinfo.c:119
IN_CLASSA_NSHIFT
#define IN_CLASSA_NSHIFT
Definition: sockport.h:61
u_short
#define u_short
Definition: vsnprintf.c:65
sockport.h
memcpy
memcpy(buf+1, str, len)
afd
Definition: getaddrinfo.c:111
NI_NUMERICHOST
#define NI_NUMERICHOST
Definition: addrinfo.h:125
strchr
char * strchr(char *, char)
ENI_NOSOCKET
#define ENI_NOSOCKET
Definition: getnameinfo.c:109
ENI_SALEN
#define ENI_SALEN
Definition: getnameinfo.c:115
else
else
Definition: bigdecimal.c:1192
ENI_SYSTEM
#define ENI_SYSTEM
Definition: getnameinfo.c:113
ENI_FAMILY
#define ENI_FAMILY
Definition: getnameinfo.c:114
if
if(RB_TYPE_P(r, T_FLOAT))
Definition: bigdecimal.c:1186
afd::a_off
int a_off
Definition: getaddrinfo.c:115
sizeof
#define sizeof(x)
Definition: zlib.c:58
sockinet::si_len
u_char si_len
Definition: getaddrinfo.c:106
NI_NOFQDN
#define NI_NOFQDN
Definition: addrinfo.h:124
IN_EXPERIMENTAL
#define IN_EXPERIMENTAL(i)
Definition: sockport.h:57
getnameinfo
int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags)
Definition: getnameinfo.c:136
ENI_NOSERVNAME
#define ENI_NOSERVNAME
Definition: getnameinfo.c:110
u_long
#define u_long
Definition: vsnprintf.c:64
sockinet::si_port
u_short si_port
Definition: getaddrinfo.c:108
NI_NAMEREQD
#define NI_NAMEREQD
Definition: addrinfo.h:126
N_INET
#define N_INET
snprintf
#define snprintf
afd::a_addrlen
int a_addrlen
Definition: getaddrinfo.c:113
NULL
#define NULL
Definition: _sdbm.c:103
IN_MULTICAST
#define IN_MULTICAST(i)
Definition: sockport.h:53
ENI_NOHOSTNAME
#define ENI_NOHOSTNAME
Definition: getnameinfo.c:111
len
size_t len
Definition: tcltklib.c:3568