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