Ruby 2.1.5p273(2014-11-13revision48405)

- 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 #ifndef HAVE_TYPE_SOCKLEN_T
75 typedef int socklen_t;
76 #endif
77
78 #include "addrinfo.h"
79 #include "sockport.h"
80
81 #define SUCCESS 0
82 #define ANY 0
83 #define YES 1
84 #define NO 0
85
86 struct sockinet {
87 u_char si_len;
88 u_char si_family;
89 u_short si_port;
90 };
91
92 static struct afd {
93 int a_af;
94 int a_addrlen;
95 int a_socklen;
96 int a_off;
97 } afdl [] = {
98 #ifdef INET6
99 #define N_INET6 0
100 {PF_INET6, sizeof(struct in6_addr),
101 sizeof(struct sockaddr_in6),
102 offsetof(struct sockaddr_in6, sin6_addr)},
103 #define N_INET 1
104 #else
105 #define N_INET 0
106 #endif
107 {PF_INET, sizeof(struct in_addr),
108 sizeof(struct sockaddr_in),
109 offsetof(struct sockaddr_in, sin_addr)},
110 {0, 0, 0, 0},
111 };
112
113 #define ENI_NOSOCKET 0
114 #define ENI_NOSERVNAME 1
115 #define ENI_NOHOSTNAME 2
116 #define ENI_MEMORY 3
117 #define ENI_SYSTEM 4
118 #define ENI_FAMILY 5
119 #define ENI_SALEN 6
120
121 #ifndef HAVE_INET_NTOP
122 static const char *
123 inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len)
124 {
125 #ifdef HAVE_INET_NTOA
126 struct in_addr in;
127 memcpy(&in.s_addr, addr, sizeof(in.s_addr));
128 snprintf(numaddr, numaddr_len, "%s", inet_ntoa(in));
129 #else
130 unsigned long x = ntohl(*(unsigned long*)addr);
131 snprintf(numaddr, numaddr_len, "%d.%d.%d.%d",
132 (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
133 (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
134 #endif
135 return numaddr;
136 }
137 #endif
138
139 int
140 getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags)
141 {
142 struct afd *afd;
143 struct hostent *hp;
144 u_short port;
145 int family, len, i;
146 char *addr, *p;
147 u_long v4a;
148 #ifdef INET6
149 u_char pfx;
150 #endif
151 int h_error;
152 char numserv[512];
153 char numaddr[512];
154
155 if (sa == NULL)
156 return ENI_NOSOCKET;
157
158 if (!VALIDATE_SOCKLEN(sa, salen)) return ENI_SALEN;
159 len = salen;
160
161 family = sa->sa_family;
162 for (i = 0; afdl[i].a_af; i++)
163 if (afdl[i].a_af == family) {
164 afd = &afdl[i];
165 goto found;
166 }
167 return ENI_FAMILY;
168
169 found:
170 if (len != afd->a_socklen) return ENI_SALEN;
171
172 port = ((struct sockinet *)sa)->si_port; /* network byte order */
173 addr = (char *)sa + afd->a_off;
174
175 if (serv == NULL || servlen == 0) {
176 /* what we should do? */
177 } else if (flags & NI_NUMERICSERV) {
178 snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
179 if (strlen(numserv) + 1 > servlen)
180 return ENI_MEMORY;
181 strcpy(serv, numserv);
182 } else {
183 #if defined(HAVE_GETSERVBYPORT)
184 struct servent *sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
185 if (sp) {
186 if (strlen(sp->s_name) + 1 > servlen)
187 return ENI_MEMORY;
188 strcpy(serv, sp->s_name);
189 } else
190 return ENI_NOSERVNAME;
191 #else
192 return ENI_NOSERVNAME;
193 #endif
194 }
195
196 switch (sa->sa_family) {
197 case AF_INET:
198 v4a = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
199 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
200 flags |= NI_NUMERICHOST;
201 v4a >>= IN_CLASSA_NSHIFT;
202 if (v4a == 0)
203 flags |= NI_NUMERICHOST;
204 break;
205 #ifdef INET6
206 case AF_INET6:
207 #ifdef HAVE_ADDR8
208 pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0];
209 #else
210 pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0];
211 #endif
212 if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
213 flags |= NI_NUMERICHOST;
214 break;
215 #endif
216 }
217 if (host == NULL || hostlen == 0) {
218 /* what should we do? */
219 } else if (flags & NI_NUMERICHOST) {
220 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
221 == NULL)
222 return ENI_SYSTEM;
223 if (strlen(numaddr) > hostlen)
224 return ENI_MEMORY;
225 strcpy(host, numaddr);
226 } else {
227 #ifdef INET6
228 hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
229 #else
230 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
231 h_error = h_errno;
232 #endif
233
234 if (hp) {
235 if (flags & NI_NOFQDN) {
236 p = strchr(hp->h_name, '.');
237 if (p) *p = '\0';
238 }
239 if (strlen(hp->h_name) + 1 > hostlen) {
240 #ifdef INET6
241 freehostent(hp);
242 #endif
243 return ENI_MEMORY;
244 }
245 strcpy(host, hp->h_name);
246 #ifdef INET6
247 freehostent(hp);
248 #endif
249 } else {
250 if (flags & NI_NAMEREQD)
251 return ENI_NOHOSTNAME;
252 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
253 == NULL)
254 return ENI_NOHOSTNAME;
255 if (strlen(numaddr) > hostlen)
256 return ENI_MEMORY;
257 strcpy(host, numaddr);
258 }
259 }
260 return SUCCESS;
261 }
afd::a_af
int a_af
Definition: getaddrinfo.c:116
SUCCESS
#define SUCCESS
Definition: getnameinfo.c:81
addrinfo.h
VALIDATE_SOCKLEN
#define VALIDATE_SOCKLEN(addr, len)
Definition: sockport.h:16
strlen
size_t strlen(const char *)
PF_INET
#define PF_INET
Definition: sockport.h:109
sockinet::si_family
u_char si_family
Definition: getaddrinfo.c:111
NI_DGRAM
#define NI_DGRAM
Definition: addrinfo.h:128
afd::a_socklen
int a_socklen
Definition: getaddrinfo.c:118
socklen_t
int socklen_t
Definition: getnameinfo.c:75
freehostent
#define freehostent
Definition: addrinfo.h:153
sockinet
Definition: getaddrinfo.c:109
ENI_MEMORY
#define ENI_MEMORY
Definition: getnameinfo.c:116
afdl
static struct afd afdl[]
NI_NUMERICSERV
#define NI_NUMERICSERV
Definition: addrinfo.h:127
snprintf
#define snprintf
Definition: subst.h:6
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:123
IN_CLASSA_NSHIFT
#define IN_CLASSA_NSHIFT
Definition: sockport.h:93
if
if((ID)(DISPID) nameid!=nameid)
Definition: win32ole.c:770
u_short
#define u_short
Definition: vsnprintf.c:65
sockport.h
socklen_t
int socklen_t
Definition: getaddrinfo.c:84
afd
Definition: getaddrinfo.c:115
NI_NUMERICHOST
#define NI_NUMERICHOST
Definition: addrinfo.h:125
strchr
char * strchr(char *, char)
ENI_NOSOCKET
#define ENI_NOSOCKET
Definition: getnameinfo.c:113
ENI_SALEN
#define ENI_SALEN
Definition: getnameinfo.c:119
ENI_SYSTEM
#define ENI_SYSTEM
Definition: getnameinfo.c:117
ENI_FAMILY
#define ENI_FAMILY
Definition: getnameinfo.c:118
afd::a_off
int a_off
Definition: getaddrinfo.c:119
sizeof
#define sizeof(x)
Definition: zlib.c:58
sockinet::si_len
u_char si_len
Definition: getaddrinfo.c:110
NI_NOFQDN
#define NI_NOFQDN
Definition: addrinfo.h:124
IN_EXPERIMENTAL
#define IN_EXPERIMENTAL(i)
Definition: sockport.h:89
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:140
ENI_NOSERVNAME
#define ENI_NOSERVNAME
Definition: getnameinfo.c:114
u_long
#define u_long
Definition: vsnprintf.c:64
sockinet::si_port
u_short si_port
Definition: getaddrinfo.c:112
NI_NAMEREQD
#define NI_NAMEREQD
Definition: addrinfo.h:126
N_INET
#define N_INET
afd::a_addrlen
int a_addrlen
Definition: getaddrinfo.c:117
NULL
#define NULL
Definition: _sdbm.c:103
IN_MULTICAST
#define IN_MULTICAST(i)
Definition: sockport.h:85
ENI_NOHOSTNAME
#define ENI_NOHOSTNAME
Definition: getnameinfo.c:115