Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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 #include <sys/socket.h>
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 #include <resolv.h>
55 #endif
56 #endif
57 #ifdef _WIN32
58 #if defined(_MSC_VER) && _MSC_VER <= 1200
59 #include <windows.h>
60 #endif
61 #include <winsock2.h>
62 #include <ws2tcpip.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 #ifndef HAVE_TYPE_SOCKLEN_T
74 typedef int socklen_t;
75 #endif
76
77 #include "addrinfo.h"
78 #include "sockport.h"
79 #include "rubysocket.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 int
122 getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags)
123 {
124 struct afd *afd;
125 struct hostent *hp;
126 u_short port;
127 int family, len, i;
128 char *addr, *p;
129 u_long v4a;
130 #ifdef INET6
131 u_char pfx;
132 #endif
133 int h_error;
134 char numserv[512];
135 char numaddr[512];
136
137 if (sa == NULL)
138 return ENI_NOSOCKET;
139
140 if (!VALIDATE_SOCKLEN(sa, salen)) return ENI_SALEN;
141 len = salen;
142
143 family = sa->sa_family;
144 for (i = 0; afdl[i].a_af; i++)
145 if (afdl[i].a_af == family) {
146 afd = &afdl[i];
147 goto found;
148 }
149 return ENI_FAMILY;
150
151 found:
152 if (len != afd->a_socklen) return ENI_SALEN;
153
154 port = ((struct sockinet *)sa)->si_port; /* network byte order */
155 addr = (char *)sa + afd->a_off;
156
157 if (serv == NULL || servlen == 0) {
158 /* what we should do? */
159 } else if (flags & NI_NUMERICSERV) {
160 snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
161 if (strlen(numserv) + 1 > servlen)
162 return ENI_MEMORY;
163 strcpy(serv, numserv);
164 } else {
165 #if defined(HAVE_GETSERVBYPORT)
166 struct servent *sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
167 if (sp) {
168 if (strlen(sp->s_name) + 1 > servlen)
169 return ENI_MEMORY;
170 strcpy(serv, sp->s_name);
171 } else
172 return ENI_NOSERVNAME;
173 #else
174 return ENI_NOSERVNAME;
175 #endif
176 }
177
178 switch (sa->sa_family) {
179 case AF_INET:
180 v4a = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
181 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
182 flags |= NI_NUMERICHOST;
183 v4a >>= IN_CLASSA_NSHIFT;
184 if (v4a == 0)
185 flags |= NI_NUMERICHOST;
186 break;
187 #ifdef INET6
188 case AF_INET6:
189 #ifdef HAVE_ADDR8
190 pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0];
191 #else
192 pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0];
193 #endif
194 if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
195 flags |= NI_NUMERICHOST;
196 break;
197 #endif
198 }
199 if (host == NULL || hostlen == 0) {
200 /* what should we do? */
201 } else if (flags & NI_NUMERICHOST) {
202 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
203 == NULL)
204 return ENI_SYSTEM;
205 if (strlen(numaddr) > hostlen)
206 return ENI_MEMORY;
207 strcpy(host, numaddr);
208 } else {
209 #ifdef INET6
210 hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
211 #else
212 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
213 h_error = h_errno;
214 #endif
215
216 if (hp) {
217 if (flags & NI_NOFQDN) {
218 p = strchr(hp->h_name, '.');
219 if (p) *p = '\0';
220 }
221 if (strlen(hp->h_name) + 1 > hostlen) {
222 #ifdef INET6
223 freehostent(hp);
224 #endif
225 return ENI_MEMORY;
226 }
227 strcpy(host, hp->h_name);
228 #ifdef INET6
229 freehostent(hp);
230 #endif
231 } else {
232 if (flags & NI_NAMEREQD)
233 return ENI_NOHOSTNAME;
234 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
235 == NULL)
236 return ENI_NOHOSTNAME;
237 if (strlen(numaddr) > hostlen)
238 return ENI_MEMORY;
239 strcpy(host, numaddr);
240 }
241 }
242 return SUCCESS;
243 }
sockinet::si_port
u_short si_port
Definition: getaddrinfo.c:111
ENI_FAMILY
#define ENI_FAMILY
Definition: getnameinfo.c:118
NI_NAMEREQD
#define NI_NAMEREQD
Definition: addrinfo.h:126
IN_MULTICAST
#define IN_MULTICAST(i)
Definition: sockport.h:85
inet_ntop
const char * inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len)
Definition: option.c:651
ENI_SYSTEM
#define ENI_SYSTEM
Definition: getnameinfo.c:117
SUCCESS
#define SUCCESS
Definition: getnameinfo.c:81
freehostent
#define freehostent
Definition: addrinfo.h:153
snprintf
int snprintf(char *__restrict, size_t, const char *__restrict,...) __attribute__((__format__(__printf__
strchr
char * strchr(char *, char)
NI_NOFQDN
#define NI_NOFQDN
Definition: addrinfo.h:124
IN_EXPERIMENTAL
#define IN_EXPERIMENTAL(i)
Definition: sockport.h:89
ENI_NOSOCKET
#define ENI_NOSOCKET
Definition: getnameinfo.c:113
offsetof
#define offsetof(p_type, field)
Definition: addrinfo.h:186
IN_CLASSA_NSHIFT
#define IN_CLASSA_NSHIFT
Definition: sockport.h:93
else
else
Definition: rb_mjit_min_header-2.7.0.h:13246
addrinfo.h
sockinet
Definition: getaddrinfo.c:108
NULL
#define NULL
Definition: _sdbm.c:101
socklen_t
int socklen_t
Definition: getaddrinfo.c:83
strlen
size_t strlen(const char *)
ENI_NOHOSTNAME
#define ENI_NOHOSTNAME
Definition: getnameinfo.c:115
if
if((ID)(DISPID) nameid !=nameid)
Definition: win32ole.c:357
N_INET
#define N_INET
NI_NUMERICHOST
#define NI_NUMERICHOST
Definition: addrinfo.h:125
VALIDATE_SOCKLEN
#define VALIDATE_SOCKLEN(addr, len)
Definition: sockport.h:16
u_long
unsigned long u_long
Definition: rb_mjit_min_header-2.7.0.h:1293
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
u_char
unsigned char u_char
Definition: rb_mjit_min_header-2.7.0.h:1287
strcpy
char * strcpy(char *__restrict, const char *__restrict)
socklen_t
int socklen_t
Definition: getnameinfo.c:74
PF_INET
#define PF_INET
Definition: sockport.h:109
ENI_SALEN
#define ENI_SALEN
Definition: getnameinfo.c:119
ENI_MEMORY
#define ENI_MEMORY
Definition: getnameinfo.c:116
NI_NUMERICSERV
#define NI_NUMERICSERV
Definition: addrinfo.h:127
ENI_NOSERVNAME
#define ENI_NOSERVNAME
Definition: getnameinfo.c:114
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:122
len
uint8_t len
Definition: escape.c:17
rubysocket.h
NI_DGRAM
#define NI_DGRAM
Definition: addrinfo.h:128
u_short
unsigned short u_short
Definition: rb_mjit_min_header-2.7.0.h:1289
sockinet::si_family
u_char si_family
Definition: getaddrinfo.c:110
sockinet::si_len
u_char si_len
Definition: getaddrinfo.c:109
sockport.h