1 /*
2 Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 Without limiting anything contained in the foregoing, this file,
16 which is part of C Driver for MySQL (Connector/C), is also subject to the
17 Universal FOSS Exception, version 1.0, a copy of which can be found at
18 http://oss.oracle.com/licenses/universal-foss-exception.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License, version 2.0, for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
28 02110-1301 USA */
29
30 /*
31 Note that we can't have assertion on file descriptors; The reason for
32 this is that during mysql shutdown, another thread can close a file
33 we are working on. In this case we should just return read errors from
34 the file descriptior.
35 */
36
37 #include "vio_priv.h"
38
39 #ifdef FIONREAD_IN_SYS_FILIO
40 # include <sys/filio.h>
41 #endif
42 #ifndef _WIN32
43 # include <netinet/tcp.h>
44 #endif
45 #ifdef HAVE_POLL_H
46 # include <poll.h>
47 #endif
48 #ifdef HAVE_SYS_IOCTL_H
49 # include <sys/ioctl.h>
50 #endif
51
vio_errno(Vio * vio MY_ATTRIBUTE ((unused)))52 int vio_errno(Vio *vio MY_ATTRIBUTE((unused)))
53 {
54 /* These transport types are not Winsock based. */
55 #ifdef _WIN32
56 if (vio->type == VIO_TYPE_NAMEDPIPE ||
57 vio->type == VIO_TYPE_SHARED_MEMORY)
58 return GetLastError();
59 #endif
60
61 /* Mapped to WSAGetLastError() on Win32. */
62 return socket_errno;
63 }
64
65
66 /**
67 Attempt to wait for an I/O event on a socket.
68
69 @param vio VIO object representing a connected socket.
70 @param event The type of I/O event (read or write) to wait for.
71
72 @return Return value is -1 on failure, 0 on success.
73 */
74
vio_socket_io_wait(Vio * vio,enum enum_vio_io_event event)75 int vio_socket_io_wait(Vio *vio, enum enum_vio_io_event event)
76 {
77 int timeout, ret;
78
79 DBUG_ASSERT(event == VIO_IO_EVENT_READ || event == VIO_IO_EVENT_WRITE);
80
81 /* Choose an appropriate timeout. */
82 if (event == VIO_IO_EVENT_READ)
83 timeout= vio->read_timeout;
84 else
85 timeout= vio->write_timeout;
86
87 /* Wait for input data to become available. */
88 switch (vio_io_wait(vio, event, timeout))
89 {
90 case -1:
91 /* Upon failure, vio_read/write() shall return -1. */
92 ret= -1;
93 break;
94 case 0:
95 /* The wait timed out. */
96 ret= -1;
97 break;
98 default:
99 /* A positive value indicates an I/O event. */
100 ret= 0;
101 break;
102 }
103
104 return ret;
105 }
106
107
108 /*
109 Define a stub MSG_DONTWAIT if unavailable. In this case, fcntl
110 (or a equivalent) is used to enable non-blocking operations.
111 The flag must be supported in both send and recv operations.
112 */
113 #if defined(__linux__)
114 #define VIO_USE_DONTWAIT 1
115 #define VIO_DONTWAIT MSG_DONTWAIT
116 #else
117 #define VIO_DONTWAIT 0
118 #endif
119
120
vio_read(Vio * vio,uchar * buf,size_t size)121 size_t vio_read(Vio *vio, uchar *buf, size_t size)
122 {
123 ssize_t ret;
124 int flags= 0;
125 DBUG_ENTER("vio_read");
126
127 /* Ensure nobody uses vio_read_buff and vio_read simultaneously. */
128 DBUG_ASSERT(vio->read_end == vio->read_pos);
129
130 /* If timeout is enabled, do not block if data is unavailable. */
131 if (vio->read_timeout >= 0)
132 flags= VIO_DONTWAIT;
133
134 while ((ret= mysql_socket_recv(vio->mysql_socket, (SOCKBUF_T *)buf, size, flags)) == -1)
135 {
136 int error= socket_errno;
137
138 /* The operation would block? */
139 if (error != SOCKET_EAGAIN && error != SOCKET_EWOULDBLOCK)
140 break;
141
142 /* Wait for input data to become available. */
143 if ((ret= vio_socket_io_wait(vio, VIO_IO_EVENT_READ)))
144 break;
145 }
146
147 DBUG_RETURN(ret);
148 }
149
150
151 /*
152 Buffered read: if average read size is small it may
153 reduce number of syscalls.
154 */
155
vio_read_buff(Vio * vio,uchar * buf,size_t size)156 size_t vio_read_buff(Vio *vio, uchar* buf, size_t size)
157 {
158 size_t rc;
159 #define VIO_UNBUFFERED_READ_MIN_SIZE 2048
160 DBUG_ENTER("vio_read_buff");
161 DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %u",
162 mysql_socket_getfd(vio->mysql_socket), (long)buf, (uint)size));
163
164 if (vio->read_pos < vio->read_end)
165 {
166 rc= MY_MIN((size_t) (vio->read_end - vio->read_pos), size);
167 memcpy(buf, vio->read_pos, rc);
168 vio->read_pos+= rc;
169 /*
170 Do not try to read from the socket now even if rc < size:
171 vio_read can return -1 due to an error or non-blocking mode, and
172 the safest way to handle it is to move to a separate branch.
173 */
174 }
175 else if (size < VIO_UNBUFFERED_READ_MIN_SIZE)
176 {
177 rc= vio_read(vio, (uchar*) vio->read_buffer, VIO_READ_BUFFER_SIZE);
178 if (rc != 0 && rc != (size_t) -1)
179 {
180 if (rc > size)
181 {
182 vio->read_pos= vio->read_buffer + size;
183 vio->read_end= vio->read_buffer + rc;
184 rc= size;
185 }
186 memcpy(buf, vio->read_buffer, rc);
187 }
188 }
189 else
190 rc= vio_read(vio, buf, size);
191 DBUG_RETURN(rc);
192 #undef VIO_UNBUFFERED_READ_MIN_SIZE
193 }
194
195
vio_buff_has_data(Vio * vio)196 my_bool vio_buff_has_data(Vio *vio)
197 {
198 return (vio->read_pos != vio->read_end);
199 }
200
201
vio_write(Vio * vio,const uchar * buf,size_t size)202 size_t vio_write(Vio *vio, const uchar* buf, size_t size)
203 {
204 ssize_t ret;
205 int flags= 0;
206 DBUG_ENTER("vio_write");
207
208 /* If timeout is enabled, do not block. */
209 if (vio->write_timeout >= 0)
210 flags= VIO_DONTWAIT;
211
212 while ((ret= mysql_socket_send(vio->mysql_socket, (SOCKBUF_T *)buf, size, flags)) == -1)
213 {
214 int error= socket_errno;
215
216 /* The operation would block? */
217 if (error != SOCKET_EAGAIN && error != SOCKET_EWOULDBLOCK)
218 break;
219
220 /* Wait for the output buffer to become writable.*/
221 if ((ret= vio_socket_io_wait(vio, VIO_IO_EVENT_WRITE)))
222 break;
223 }
224
225 DBUG_RETURN(ret);
226 }
227
228 //WL#4896: Not covered
vio_set_blocking(Vio * vio,my_bool status)229 static int vio_set_blocking(Vio *vio, my_bool status)
230 {
231 DBUG_ENTER("vio_set_blocking");
232
233 #ifdef _WIN32
234 DBUG_ASSERT(vio->type != VIO_TYPE_NAMEDPIPE);
235 DBUG_ASSERT(vio->type != VIO_TYPE_SHARED_MEMORY);
236 {
237 int ret;
238 u_long arg= status ? 0 : 1;
239 ret= ioctlsocket(mysql_socket_getfd(vio->mysql_socket), FIONBIO, &arg);
240 DBUG_RETURN(ret);
241 }
242 #else
243 {
244 int flags;
245
246 if ((flags= fcntl(mysql_socket_getfd(vio->mysql_socket), F_GETFL, NULL)) < 0)
247 DBUG_RETURN(-1);
248
249 /*
250 Always set/clear the flag to avoid inheritance issues. This is
251 a issue mainly on Mac OS X Tiger (version 10.4) where although
252 the O_NONBLOCK flag is inherited from the parent socket, the
253 actual non-blocking behavior is not inherited.
254 */
255 if (status)
256 flags&= ~O_NONBLOCK;
257 else
258 flags|= O_NONBLOCK;
259
260 if (fcntl(mysql_socket_getfd(vio->mysql_socket), F_SETFL, flags) == -1)
261 DBUG_RETURN(-1);
262 }
263 #endif
264
265 DBUG_RETURN(0);
266 }
267
268
vio_socket_timeout(Vio * vio,uint which MY_ATTRIBUTE ((unused)),my_bool old_mode MY_ATTRIBUTE ((unused)))269 int vio_socket_timeout(Vio *vio,
270 uint which MY_ATTRIBUTE((unused)),
271 my_bool old_mode MY_ATTRIBUTE((unused)))
272 {
273 int ret= 0;
274 DBUG_ENTER("vio_socket_timeout");
275
276 #if defined(_WIN32)
277 {
278 int optname;
279 DWORD timeout= 0;
280 const char *optval= (const char *) &timeout;
281
282 /*
283 The default socket timeout value is zero, which means an infinite
284 timeout. Values less than 500 milliseconds are interpreted to be of
285 500 milliseconds. Hence, the VIO behavior for zero timeout, which is
286 intended to cause the send or receive operation to fail immediately
287 if no data is available, is not supported on WIN32 and neither is
288 necessary as it's not possible to set the VIO timeout value to zero.
289
290 Assert that the VIO timeout is either positive or set to infinite.
291 */
292 DBUG_ASSERT(which || vio->read_timeout);
293 DBUG_ASSERT(!which || vio->write_timeout);
294
295 if (which)
296 {
297 optname= SO_SNDTIMEO;
298 if (vio->write_timeout > 0)
299 timeout= vio->write_timeout;
300 }
301 else
302 {
303 optname= SO_RCVTIMEO;
304 if (vio->read_timeout > 0)
305 timeout= vio->read_timeout;
306 }
307
308 ret= mysql_socket_setsockopt(vio->mysql_socket, SOL_SOCKET, optname,
309 optval, sizeof(timeout));
310 }
311 #else
312 /*
313 The MSG_DONTWAIT trick is not used with SSL sockets as the send and
314 receive I/O operations are wrapped through SSL-specific functions
315 (SSL_read and SSL_write) which are not equivalent to the standard
316 recv(2) and send(2) used in vio_read() and vio_write(). Hence, the
317 socket blocking mode is changed and vio_io_wait() is used to wait
318 for I/O or timeout.
319 */
320 #ifdef VIO_USE_DONTWAIT
321 if (vio->type == VIO_TYPE_SSL)
322 #endif
323 {
324 /* Deduce what should be the new blocking mode of the socket. */
325 my_bool new_mode= vio->write_timeout < 0 && vio->read_timeout < 0;
326
327 /* If necessary, update the blocking mode. */
328 if (new_mode != old_mode)
329 ret= vio_set_blocking(vio, new_mode);
330 }
331 #endif
332
333 DBUG_RETURN(ret);
334 }
335
336
vio_fastsend(Vio * vio MY_ATTRIBUTE ((unused)))337 int vio_fastsend(Vio * vio MY_ATTRIBUTE((unused)))
338 {
339 int r=0;
340 DBUG_ENTER("vio_fastsend");
341
342 #if defined(IPTOS_THROUGHPUT)
343 {
344 int tos = IPTOS_THROUGHPUT;
345 r= mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_IP, IP_TOS,
346 (void *)&tos, sizeof(tos));
347 }
348 #endif /* IPTOS_THROUGHPUT */
349 if (!r)
350 {
351 #ifdef _WIN32
352 BOOL nodelay= 1;
353 #else
354 int nodelay = 1;
355 #endif
356
357 r= mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_TCP, TCP_NODELAY,
358 IF_WIN((const char*), (void*)) &nodelay,
359 sizeof(nodelay));
360
361 }
362 if (r)
363 {
364 DBUG_PRINT("warning", ("Couldn't set socket option for fast send"));
365 r= -1;
366 }
367 DBUG_PRINT("exit", ("%d", r));
368 DBUG_RETURN(r);
369 }
370
vio_keepalive(Vio * vio,my_bool set_keep_alive)371 int vio_keepalive(Vio* vio, my_bool set_keep_alive)
372 {
373 int r=0;
374 uint opt = 0;
375 DBUG_ENTER("vio_keepalive");
376 DBUG_PRINT("enter", ("sd: %d set_keep_alive: %d",
377 mysql_socket_getfd(vio->mysql_socket), (int)set_keep_alive));
378 if (vio->type != VIO_TYPE_NAMEDPIPE)
379 {
380 if (set_keep_alive)
381 opt = 1;
382 r = mysql_socket_setsockopt(vio->mysql_socket, SOL_SOCKET, SO_KEEPALIVE,
383 (char *)&opt, sizeof(opt));
384 }
385 DBUG_RETURN(r);
386 }
387
388
389 /**
390 Indicate whether a I/O operation must be retried later.
391
392 @param vio A VIO object
393
394 @return Whether a I/O operation should be deferred.
395 @retval TRUE Temporary failure, retry operation.
396 @retval FALSE Indeterminate failure.
397 */
398
399 my_bool
vio_should_retry(Vio * vio)400 vio_should_retry(Vio *vio)
401 {
402 return (vio_errno(vio) == SOCKET_EINTR);
403 }
404
405
406 /**
407 Indicate whether a I/O operation timed out.
408
409 @param vio A VIO object
410
411 @return Whether a I/O operation timed out.
412 @retval TRUE Operation timed out.
413 @retval FALSE Not a timeout failure.
414 */
415
416 my_bool
vio_was_timeout(Vio * vio)417 vio_was_timeout(Vio *vio)
418 {
419 return (vio_errno(vio) == SOCKET_ETIMEDOUT);
420 }
421
422
vio_shutdown(Vio * vio)423 int vio_shutdown(Vio * vio)
424 {
425 int r=0;
426 DBUG_ENTER("vio_shutdown");
427
428 if (vio->inactive == FALSE)
429 {
430 DBUG_ASSERT(vio->type == VIO_TYPE_TCPIP ||
431 vio->type == VIO_TYPE_SOCKET ||
432 vio->type == VIO_TYPE_SSL);
433
434 DBUG_ASSERT(mysql_socket_getfd(vio->mysql_socket) >= 0);
435 if (mysql_socket_shutdown(vio->mysql_socket, SHUT_RDWR))
436 r= -1;
437 if (mysql_socket_close(vio->mysql_socket))
438 r= -1;
439 }
440 if (r)
441 {
442 DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno));
443 /* FIXME: error handling (not critical for MySQL) */
444 }
445 vio->inactive= TRUE;
446 vio->mysql_socket= MYSQL_INVALID_SOCKET;
447 DBUG_RETURN(r);
448 }
449
450
vio_description(Vio * vio)451 const char *vio_description(Vio * vio)
452 {
453 if (!vio->desc[0])
454 {
455 my_snprintf(vio->desc, VIO_DESCRIPTION_SIZE,
456 (vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"),
457 mysql_socket_getfd(vio->mysql_socket));
458 }
459 return vio->desc;
460 }
461
vio_type(Vio * vio)462 enum enum_vio_type vio_type(Vio* vio)
463 {
464 return vio->type;
465 }
466
vio_fd(Vio * vio)467 my_socket vio_fd(Vio* vio)
468 {
469 return mysql_socket_getfd(vio->mysql_socket);
470 }
471
472 /**
473 Convert a sock-address (AF_INET or AF_INET6) into the "normalized" form,
474 which is the IPv4 form for IPv4-mapped or IPv4-compatible IPv6 addresses.
475
476 @note Background: when IPv4 and IPv6 are used simultaneously, IPv4
477 addresses may be written in a form of IPv4-mapped or IPv4-compatible IPv6
478 addresses. That means, one address (a.b.c.d) can be written in three forms:
479 - IPv4: a.b.c.d;
480 - IPv4-compatible IPv6: ::a.b.c.d;
481 - IPv4-mapped IPv4: ::ffff:a.b.c.d;
482
483 Having three forms of one address makes it a little difficult to compare
484 addresses with each other (the IPv4-compatible IPv6-address of foo.bar
485 will be different from the IPv4-mapped IPv6-address of foo.bar).
486
487 @note This function can be made public when it's needed.
488
489 @param src [in] source IP address (AF_INET or AF_INET6).
490 @param src_length [in] length of the src.
491 @param dst [out] a buffer to store normalized IP address
492 (sockaddr_storage).
493 @param dst_length [out] actual length of the normalized IP address.
494 */
vio_get_normalized_ip(const struct sockaddr * src,size_t src_length,struct sockaddr * dst,size_t * dst_length)495 static void vio_get_normalized_ip(const struct sockaddr *src,
496 size_t src_length,
497 struct sockaddr *dst,
498 size_t *dst_length)
499 {
500 switch (src->sa_family) {
501 case AF_INET:
502 memcpy(dst, src, src_length);
503 *dst_length= src_length;
504 break;
505
506 #ifdef HAVE_IPV6
507 case AF_INET6:
508 {
509 const struct sockaddr_in6 *src_addr6= (const struct sockaddr_in6 *) src;
510 const struct in6_addr *src_ip6= &(src_addr6->sin6_addr);
511 const uint32 *src_ip6_int32= (uint32 *) src_ip6->s6_addr;
512
513 if (IN6_IS_ADDR_V4MAPPED(src_ip6) || IN6_IS_ADDR_V4COMPAT(src_ip6))
514 {
515 struct sockaddr_in *dst_ip4= (struct sockaddr_in *) dst;
516
517 /*
518 This is an IPv4-mapped or IPv4-compatible IPv6 address. It should
519 be converted to the IPv4 form.
520 */
521
522 *dst_length= sizeof (struct sockaddr_in);
523
524 memset(dst_ip4, 0, *dst_length);
525 dst_ip4->sin_family= AF_INET;
526 dst_ip4->sin_port= src_addr6->sin6_port;
527
528 /*
529 In an IPv4 mapped or compatible address, the last 32 bits represent
530 the IPv4 address. The byte orders for IPv6 and IPv4 addresses are
531 the same, so a simple copy is possible.
532 */
533 dst_ip4->sin_addr.s_addr= src_ip6_int32[3];
534 }
535 else
536 {
537 /* This is a "native" IPv6 address. */
538
539 memcpy(dst, src, src_length);
540 *dst_length= src_length;
541 }
542
543 break;
544 }
545 #endif /* HAVE_IPV6 */
546 }
547 }
548
549
550 /**
551 Return the normalized IP address string for a sock-address.
552
553 The idea is to return an IPv4-address for an IPv4-mapped and
554 IPv4-compatible IPv6 address.
555
556 The function writes the normalized IP address to the given buffer.
557 The buffer should have enough space, otherwise error flag is returned.
558 The system constant INET6_ADDRSTRLEN can be used to reserve buffers of
559 the right size.
560
561 @param addr [in] sockaddr object (AF_INET or AF_INET6).
562 @param addr_length [in] length of the addr.
563 @param ip_string [out] buffer to write normalized IP address.
564 @param ip_string_size [in] size of the ip_string.
565
566 @return Error status.
567 @retval TRUE in case of error (the ip_string buffer is not enough).
568 @retval FALSE on success.
569 */
570
vio_get_normalized_ip_string(const struct sockaddr * addr,size_t addr_length,char * ip_string,size_t ip_string_size)571 my_bool vio_get_normalized_ip_string(const struct sockaddr *addr,
572 size_t addr_length,
573 char *ip_string,
574 size_t ip_string_size)
575 {
576 struct sockaddr_storage norm_addr_storage;
577 struct sockaddr *norm_addr= (struct sockaddr *) &norm_addr_storage;
578 size_t norm_addr_length;
579 int err_code;
580
581 vio_get_normalized_ip(addr, addr_length, norm_addr, &norm_addr_length);
582
583 err_code= vio_getnameinfo(norm_addr, ip_string, ip_string_size, NULL, 0,
584 NI_NUMERICHOST);
585
586 if (!err_code)
587 return FALSE;
588
589 DBUG_PRINT("error", ("getnameinfo() failed with %d (%s).",
590 (int) err_code,
591 (const char *) gai_strerror(err_code)));
592 return TRUE;
593 }
594
595
596 /**
597 Return IP address and port of a VIO client socket.
598
599 The function returns an IPv4 address if IPv6 support is disabled.
600
601 The function returns an IPv4 address if the client socket is associated
602 with an IPv4-compatible or IPv4-mapped IPv6 address. Otherwise, the native
603 IPv6 address is returned.
604 */
605
vio_peer_addr(Vio * vio,char * ip_buffer,uint16 * port,size_t ip_buffer_size)606 my_bool vio_peer_addr(Vio *vio, char *ip_buffer, uint16 *port,
607 size_t ip_buffer_size)
608 {
609 DBUG_ENTER("vio_peer_addr");
610 DBUG_PRINT("enter", ("Client socked fd: %d",
611 (int)mysql_socket_getfd(vio->mysql_socket)));
612
613 if (vio->localhost)
614 {
615 /*
616 Initialize vio->remote and vio->addLen. Set vio->remote to IPv4 loopback
617 address.
618 */
619 struct in_addr *ip4= &((struct sockaddr_in *) &(vio->remote))->sin_addr;
620
621 vio->remote.ss_family= AF_INET;
622 vio->addrLen= sizeof (struct sockaddr_in);
623
624 ip4->s_addr= htonl(INADDR_LOOPBACK);
625
626 /* Initialize ip_buffer and port. */
627
628 my_stpcpy(ip_buffer, "127.0.0.1");
629 *port= 0;
630 }
631 else
632 {
633 int err_code;
634 char port_buffer[NI_MAXSERV];
635
636 struct sockaddr_storage addr_storage;
637 struct sockaddr *addr= (struct sockaddr *) &addr_storage;
638 socket_len_t addr_length= sizeof (addr_storage);
639
640 /* Get sockaddr by socked fd. */
641
642 err_code= mysql_socket_getpeername(vio->mysql_socket, addr, &addr_length);
643
644 if (err_code)
645 {
646 DBUG_PRINT("exit", ("getpeername() gave error: %d", socket_errno));
647 DBUG_RETURN(TRUE);
648 }
649
650 /* Normalize IP address. */
651
652 vio_get_normalized_ip(addr, addr_length,
653 (struct sockaddr *) &vio->remote, &vio->addrLen);
654
655 /* Get IP address & port number. */
656
657 err_code= vio_getnameinfo((struct sockaddr *) &vio->remote,
658 ip_buffer, ip_buffer_size,
659 port_buffer, NI_MAXSERV,
660 NI_NUMERICHOST | NI_NUMERICSERV);
661
662 if (err_code)
663 {
664 DBUG_PRINT("exit", ("getnameinfo() gave error: %s",
665 gai_strerror(err_code)));
666 DBUG_RETURN(TRUE);
667 }
668
669 *port= (uint16) strtol(port_buffer, NULL, 10);
670 }
671
672 DBUG_PRINT("exit", ("Client IP address: %s; port: %d",
673 (const char *) ip_buffer,
674 (int) *port));
675 DBUG_RETURN(FALSE);
676 }
677
678
679 /**
680 Retrieve the amount of data that can be read from a socket.
681
682 @param vio A VIO object.
683 @param bytes[out] The amount of bytes available.
684
685 @retval FALSE Success.
686 @retval TRUE Failure.
687 */
688 // WL#4896: Not covered
socket_peek_read(Vio * vio,uint * bytes)689 static my_bool socket_peek_read(Vio *vio, uint *bytes)
690 {
691 my_socket sd= mysql_socket_getfd(vio->mysql_socket);
692 #if defined(_WIN32)
693 int len;
694 if (ioctlsocket(sd, FIONREAD, &len))
695 return TRUE;
696 *bytes= len;
697 return FALSE;
698 #elif defined(FIONREAD_IN_SYS_IOCTL) || defined(FIONREAD_IN_SYS_FILIO)
699 int len;
700 if (ioctl(sd, FIONREAD, &len) < 0)
701 return TRUE;
702 *bytes= len;
703 return FALSE;
704 #else
705 char buf[1024];
706 ssize_t res= recv(sd, &buf, sizeof(buf), MSG_PEEK);
707 if (res < 0)
708 return TRUE;
709 *bytes= res;
710 return FALSE;
711 #endif
712 }
713
714 #ifndef _WIN32
715
716 /**
717 Set of event flags grouped by operations.
718 */
719
720 /*
721 Linux specific flag used to detect connection shutdown. The flag is
722 also used for half-closed notification, which here is interpreted as
723 if there is data available to be read from the socket.
724 */
725 #ifndef POLLRDHUP
726 #define POLLRDHUP 0
727 #endif
728
729 /* Data may be read. */
730 #define MY_POLL_SET_IN (POLLIN | POLLPRI)
731 /* Data may be written. */
732 #define MY_POLL_SET_OUT (POLLOUT)
733 /* An error or hangup. */
734 #define MY_POLL_SET_ERR (POLLERR | POLLHUP | POLLNVAL)
735
736 #endif
737
738 /**
739 Wait for an I/O event on a VIO socket.
740
741 @param vio VIO object representing a connected socket.
742 @param event The type of I/O event to wait for.
743 @param timeout Interval (in milliseconds) to wait for an I/O event.
744 A negative timeout value means an infinite timeout.
745
746 @remark sock_errno is set to SOCKET_ETIMEDOUT on timeout.
747
748 @return A three-state value which indicates the operation status.
749 @retval -1 Failure, socket_errno indicates the error.
750 @retval 0 The wait has timed out.
751 @retval 1 The requested I/O event has occurred.
752 */
753
754 #if !defined(_WIN32) && !defined(__APPLE__)
vio_io_wait(Vio * vio,enum enum_vio_io_event event,int timeout)755 int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout)
756 {
757 int ret;
758 #ifndef DBUG_OFF
759 short revents= 0;
760 #endif
761 struct pollfd pfd;
762 my_socket sd= mysql_socket_getfd(vio->mysql_socket);
763 MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */
764 DBUG_ENTER("vio_io_wait");
765
766 memset(&pfd, 0, sizeof(pfd));
767
768 pfd.fd= sd;
769
770 /*
771 Set the poll bitmask describing the type of events.
772 The error flags are only valid in the revents bitmask.
773 */
774 switch (event)
775 {
776 case VIO_IO_EVENT_READ:
777 pfd.events= MY_POLL_SET_IN;
778 #ifndef DBUG_OFF
779 revents= MY_POLL_SET_IN | MY_POLL_SET_ERR | POLLRDHUP;
780 #endif
781 break;
782 case VIO_IO_EVENT_WRITE:
783 case VIO_IO_EVENT_CONNECT:
784 pfd.events= MY_POLL_SET_OUT;
785 #ifndef DBUG_OFF
786 revents= MY_POLL_SET_OUT | MY_POLL_SET_ERR;
787 #endif
788 break;
789 }
790
791 MYSQL_START_SOCKET_WAIT(locker, &state, vio->mysql_socket, PSI_SOCKET_SELECT, 0);
792
793 /*
794 Wait for the I/O event and return early in case of
795 error or timeout.
796 */
797 switch ((ret= poll(&pfd, 1, timeout)))
798 {
799 case -1:
800 /* On error, -1 is returned. */
801 break;
802 case 0:
803 /*
804 Set errno to indicate a timeout error.
805 (This is not compiled in on WIN32.)
806 */
807 errno= SOCKET_ETIMEDOUT;
808 break;
809 default:
810 /* Ensure that the requested I/O event has completed. */
811 DBUG_ASSERT(pfd.revents & revents);
812 break;
813 }
814
815 MYSQL_END_SOCKET_WAIT(locker, 0);
816 DBUG_RETURN(ret);
817 }
818
819 #else
820
vio_io_wait(Vio * vio,enum enum_vio_io_event event,int timeout)821 int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout)
822 {
823 int ret;
824 struct timeval tm;
825 my_socket fd;
826 fd_set readfds, writefds, exceptfds;
827 MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */
828 DBUG_ENTER("vio_io_wait");
829
830 fd= mysql_socket_getfd(vio->mysql_socket);
831
832 if (fd == INVALID_SOCKET)
833 DBUG_RETURN(-1);
834
835 #ifdef __APPLE__
836 if (fd >= FD_SETSIZE)
837 DBUG_RETURN(-1);
838 #endif
839
840 /* Convert the timeout, in milliseconds, to seconds and microseconds. */
841 if (timeout >= 0)
842 {
843 tm.tv_sec= timeout / 1000;
844 tm.tv_usec= (timeout % 1000) * 1000;
845 }
846
847 FD_ZERO(&readfds);
848 FD_ZERO(&writefds);
849 FD_ZERO(&exceptfds);
850
851 /* Always receive notification of exceptions. */
852 FD_SET(fd, &exceptfds);
853
854 switch (event)
855 {
856 case VIO_IO_EVENT_READ:
857 /* Readiness for reading. */
858 FD_SET(fd, &readfds);
859 break;
860 case VIO_IO_EVENT_WRITE:
861 case VIO_IO_EVENT_CONNECT:
862 /* Readiness for writing. */
863 FD_SET(fd, &writefds);
864 break;
865 }
866
867 MYSQL_START_SOCKET_WAIT(locker, &state, vio->mysql_socket, PSI_SOCKET_SELECT, 0);
868
869 /* The first argument is ignored on Windows. */
870 ret= select((int)(fd + 1), &readfds, &writefds, &exceptfds,
871 (timeout >= 0) ? &tm : NULL);
872
873 MYSQL_END_SOCKET_WAIT(locker, 0);
874
875 /* Set error code to indicate a timeout error. */
876 if (ret == 0)
877 #if defined(_WIN32)
878 WSASetLastError(SOCKET_ETIMEDOUT);
879 #elif defined(__APPLE__)
880 errno= SOCKET_ETIMEDOUT;
881 #else
882 #error Oops...Wrong OS
883 #endif
884
885 /* Error or timeout? */
886 if (ret <= 0)
887 DBUG_RETURN(ret);
888
889 /* The requested I/O event is ready? */
890 switch (event)
891 {
892 case VIO_IO_EVENT_READ:
893 ret= MY_TEST(FD_ISSET(fd, &readfds));
894 break;
895 case VIO_IO_EVENT_WRITE:
896 case VIO_IO_EVENT_CONNECT:
897 ret= MY_TEST(FD_ISSET(fd, &writefds));
898 break;
899 }
900
901 /* Error conditions pending? */
902 ret|= MY_TEST(FD_ISSET(fd, &exceptfds));
903
904 /* Not a timeout, ensure that a condition was met. */
905 DBUG_ASSERT(ret);
906
907 DBUG_RETURN(ret);
908 }
909
910 #endif /* _WIN32 */
911
912
913 /**
914 Connect to a peer address.
915
916 @param vio A VIO object.
917 @param addr Socket address containing the peer address.
918 @param len Length of socket address.
919 @param timeout Interval (in milliseconds) to wait until a
920 connection is established.
921
922 @retval FALSE A connection was successfully established.
923 @retval TRUE A fatal error. See socket_errno.
924 */
925
926 my_bool
vio_socket_connect(Vio * vio,struct sockaddr * addr,socklen_t len,int timeout)927 vio_socket_connect(Vio *vio, struct sockaddr *addr, socklen_t len, int timeout)
928 {
929 int ret, wait;
930 DBUG_ENTER("vio_socket_connect");
931
932 /* Only for socket-based transport types. */
933 DBUG_ASSERT(vio->type == VIO_TYPE_SOCKET || vio->type == VIO_TYPE_TCPIP);
934
935 /* If timeout is not infinite, set socket to non-blocking mode. */
936 if ((timeout > -1) && vio_set_blocking(vio, FALSE))
937 DBUG_RETURN(TRUE);
938
939 /* Initiate the connection. */
940 ret= mysql_socket_connect(vio->mysql_socket, addr, len);
941
942 #ifdef _WIN32
943 wait= (ret == SOCKET_ERROR) &&
944 (WSAGetLastError() == WSAEINPROGRESS ||
945 WSAGetLastError() == WSAEWOULDBLOCK);
946 #else
947 wait= (ret == -1) && (errno == EINPROGRESS || errno == EALREADY);
948 #endif
949
950 /*
951 The connection is in progress. The vio_io_wait() call can be used
952 to wait up to a specified period of time for the connection to
953 succeed.
954
955 If vio_io_wait() returns 0 (after waiting however many seconds),
956 the socket never became writable (host is probably unreachable.)
957 Otherwise, if vio_io_wait() returns 1, then one of two conditions
958 exist:
959
960 1. An error occurred. Use getsockopt() to check for this.
961 2. The connection was set up successfully: getsockopt() will
962 return 0 as an error.
963 */
964 if (wait && (vio_io_wait(vio, VIO_IO_EVENT_CONNECT, timeout) == 1))
965 {
966 int error;
967 IF_WIN(int, socklen_t) optlen= sizeof(error);
968 IF_WIN(char, void) *optval= (IF_WIN(char, void) *) &error;
969
970 /*
971 At this point, we know that something happened on the socket.
972 But this does not means that everything is alright. The connect
973 might have failed. We need to retrieve the error code from the
974 socket layer. We must return success only if we are sure that
975 it was really a success. Otherwise we might prevent the caller
976 from trying another address to connect to.
977 */
978 if (!(ret= mysql_socket_getsockopt(vio->mysql_socket, SOL_SOCKET, SO_ERROR, optval, &optlen)))
979 {
980 #ifdef _WIN32
981 WSASetLastError(error);
982 #else
983 errno= error;
984 #endif
985 ret= MY_TEST(error);
986 }
987 }
988
989 /* If necessary, restore the blocking mode, but only if connect succeeded. */
990 if ((timeout > -1) && (ret == 0))
991 {
992 if (vio_set_blocking(vio, TRUE))
993 DBUG_RETURN(TRUE);
994 }
995
996 DBUG_RETURN(MY_TEST(ret));
997 }
998
999
1000 /**
1001 Determine if the endpoint of a connection is still available.
1002
1003 @remark The socket is assumed to be disconnected if an EOF
1004 condition is encountered.
1005
1006 @param vio The VIO object.
1007
1008 @retval TRUE EOF condition not found.
1009 @retval FALSE EOF condition is signaled.
1010 */
1011
vio_is_connected(Vio * vio)1012 my_bool vio_is_connected(Vio *vio)
1013 {
1014 uint bytes= 0;
1015 DBUG_ENTER("vio_is_connected");
1016
1017 /*
1018 The first step of detecting an EOF condition is verifying
1019 whether there is data to read. Data in this case would be
1020 the EOF. An exceptional condition event and/or errors are
1021 interpreted as if there is data to read.
1022 */
1023 if (!vio_io_wait(vio, VIO_IO_EVENT_READ, 0))
1024 DBUG_RETURN(TRUE);
1025
1026 /*
1027 The second step is read() or recv() from the socket returning
1028 0 (EOF). Unfortunately, it's not possible to call read directly
1029 as we could inadvertently read meaningful connection data.
1030 Simulate a read by retrieving the number of bytes available to
1031 read -- 0 meaning EOF. In the presence of unrecoverable errors,
1032 the socket is assumed to be disconnected.
1033 */
1034 while (socket_peek_read(vio, &bytes))
1035 {
1036 if (socket_errno != SOCKET_EINTR)
1037 DBUG_RETURN(FALSE);
1038 }
1039
1040 #ifdef HAVE_OPENSSL
1041 /* There might be buffered data at the SSL layer. */
1042 if (!bytes && vio->type == VIO_TYPE_SSL)
1043 bytes= SSL_pending((SSL*) vio->ssl_arg);
1044 #endif
1045
1046 DBUG_RETURN(bytes ? TRUE : FALSE);
1047 }
1048
1049 #ifndef DBUG_OFF
1050
1051 /**
1052 Number of bytes in the read or socket buffer
1053
1054 @remark An EOF condition might count as one readable byte.
1055
1056 @return number of bytes in one of the buffers or < 0 if error.
1057 */
1058
vio_pending(Vio * vio)1059 ssize_t vio_pending(Vio *vio)
1060 {
1061 uint bytes= 0;
1062
1063 /* Data pending on the read buffer. */
1064 if (vio->read_pos < vio->read_end)
1065 return vio->read_end - vio->read_pos;
1066
1067 /* Skip non-socket based transport types. */
1068 if (vio->type == VIO_TYPE_TCPIP || vio->type == VIO_TYPE_SOCKET)
1069 {
1070 /* Obtain number of readable bytes in the socket buffer. */
1071 if (socket_peek_read(vio, &bytes))
1072 return -1;
1073 }
1074
1075 return (ssize_t) bytes;
1076 }
1077
1078 #endif
1079
1080 /**
1081 Checks if the error code, returned by vio_getnameinfo(), means it was the
1082 "No-name" error.
1083
1084 Windows-specific note: getnameinfo() returns WSANO_DATA instead of
1085 EAI_NODATA or EAI_NONAME when no reverse mapping is available at the host
1086 (i.e. Windows can't get hostname by IP-address). This error should be
1087 treated as EAI_NONAME.
1088
1089 @return if the error code is actually EAI_NONAME.
1090 @retval true if the error code is EAI_NONAME.
1091 @retval false otherwise.
1092 */
1093
vio_is_no_name_error(int err_code)1094 my_bool vio_is_no_name_error(int err_code)
1095 {
1096 #ifdef _WIN32
1097
1098 return err_code == WSANO_DATA || err_code == EAI_NONAME;
1099
1100 #else
1101
1102 return err_code == EAI_NONAME;
1103
1104 #endif
1105 }
1106
1107
1108 /**
1109 This is a wrapper for the system getnameinfo(), because different OS
1110 differ in the getnameinfo() implementation:
1111 - Solaris 10 requires that the 2nd argument (salen) must match the
1112 actual size of the struct sockaddr_storage passed to it;
1113 - Mac OS X has sockaddr_in::sin_len and sockaddr_in6::sin6_len and
1114 requires them to be filled.
1115 */
1116
vio_getnameinfo(const struct sockaddr * sa,char * hostname,size_t hostname_size,char * port,size_t port_size,int flags)1117 int vio_getnameinfo(const struct sockaddr *sa,
1118 char *hostname, size_t hostname_size,
1119 char *port, size_t port_size,
1120 int flags)
1121 {
1122 int sa_length= 0;
1123
1124 switch (sa->sa_family) {
1125 case AF_INET:
1126 sa_length= sizeof (struct sockaddr_in);
1127 #ifdef HAVE_SOCKADDR_IN_SIN_LEN
1128 ((struct sockaddr_in *) sa)->sin_len= sa_length;
1129 #endif /* HAVE_SOCKADDR_IN_SIN_LEN */
1130 break;
1131
1132 #ifdef HAVE_IPV6
1133 case AF_INET6:
1134 sa_length= sizeof (struct sockaddr_in6);
1135 # ifdef HAVE_SOCKADDR_IN6_SIN6_LEN
1136 ((struct sockaddr_in6 *) sa)->sin6_len= sa_length;
1137 # endif /* HAVE_SOCKADDR_IN6_SIN6_LEN */
1138 break;
1139 #endif /* HAVE_IPV6 */
1140 }
1141
1142 return getnameinfo(sa, sa_length,
1143 hostname, hostname_size,
1144 port, port_size,
1145 flags);
1146 }
1147