1 /*
2    Copyright (c) 2001, 2021, Oracle and/or its affiliates.
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   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   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   assert(vio->type != VIO_TYPE_NAMEDPIPE);
235   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     assert(which || vio->read_timeout);
293     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     assert(vio->type ==  VIO_TYPE_TCPIP ||
431            vio->type == VIO_TYPE_SOCKET ||
432            vio->type == VIO_TYPE_SSL);
433 
434     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 NDEBUG
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 #ifdef WITH_WSREP
767   if (sd == INVALID_SOCKET)
768     DBUG_RETURN(-1);
769 #endif /* WITH_WSREP */
770 
771   memset(&pfd, 0, sizeof(pfd));
772 
773   pfd.fd= sd;
774 
775   /*
776     Set the poll bitmask describing the type of events.
777     The error flags are only valid in the revents bitmask.
778   */
779   switch (event)
780   {
781   case VIO_IO_EVENT_READ:
782     pfd.events= MY_POLL_SET_IN;
783 #ifndef NDEBUG
784     revents= MY_POLL_SET_IN | MY_POLL_SET_ERR | POLLRDHUP;
785 #endif
786     break;
787   case VIO_IO_EVENT_WRITE:
788   case VIO_IO_EVENT_CONNECT:
789     pfd.events= MY_POLL_SET_OUT;
790 #ifndef NDEBUG
791     revents= MY_POLL_SET_OUT | MY_POLL_SET_ERR;
792 #endif
793     break;
794   }
795 
796   MYSQL_START_SOCKET_WAIT(locker, &state, vio->mysql_socket, PSI_SOCKET_SELECT, 0);
797 
798   /*
799     Wait for the I/O event and return early in case of
800     error or timeout.
801   */
802   switch ((ret= poll(&pfd, 1, timeout)))
803   {
804   case -1:
805     /* On error, -1 is returned. */
806     break;
807   case 0:
808     /*
809       Set errno to indicate a timeout error.
810       (This is not compiled in on WIN32.)
811     */
812     errno= SOCKET_ETIMEDOUT;
813     break;
814   default:
815     /* Ensure that the requested I/O event has completed. */
816     assert(pfd.revents & revents);
817     break;
818   }
819 
820   MYSQL_END_SOCKET_WAIT(locker, 0);
821   DBUG_RETURN(ret);
822 }
823 
824 #else
825 
vio_io_wait(Vio * vio,enum enum_vio_io_event event,int timeout)826 int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout)
827 {
828   int ret;
829   struct timeval tm;
830   my_socket fd;
831   fd_set readfds, writefds, exceptfds;
832   MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */
833   DBUG_ENTER("vio_io_wait");
834 
835   fd= mysql_socket_getfd(vio->mysql_socket);
836 
837   if (fd == INVALID_SOCKET)
838     DBUG_RETURN(-1);
839 
840 #ifdef __APPLE__
841   if (fd >= FD_SETSIZE)
842     DBUG_RETURN(-1);
843 #endif
844 
845   /* Convert the timeout, in milliseconds, to seconds and microseconds. */
846   if (timeout >= 0)
847   {
848     tm.tv_sec= timeout / 1000;
849     tm.tv_usec= (timeout % 1000) * 1000;
850   }
851 
852   FD_ZERO(&readfds);
853   FD_ZERO(&writefds);
854   FD_ZERO(&exceptfds);
855 
856   /* Always receive notification of exceptions. */
857   FD_SET(fd, &exceptfds);
858 
859   switch (event)
860   {
861   case VIO_IO_EVENT_READ:
862     /* Readiness for reading. */
863     FD_SET(fd, &readfds);
864     break;
865   case VIO_IO_EVENT_WRITE:
866   case VIO_IO_EVENT_CONNECT:
867     /* Readiness for writing. */
868     FD_SET(fd, &writefds);
869     break;
870   }
871 
872   MYSQL_START_SOCKET_WAIT(locker, &state, vio->mysql_socket, PSI_SOCKET_SELECT, 0);
873 
874   /* The first argument is ignored on Windows. */
875   ret= select((int)(fd + 1), &readfds, &writefds, &exceptfds,
876               (timeout >= 0) ? &tm : NULL);
877 
878   MYSQL_END_SOCKET_WAIT(locker, 0);
879 
880   /* Set error code to indicate a timeout error. */
881   if (ret == 0)
882 #if defined(_WIN32)
883     WSASetLastError(SOCKET_ETIMEDOUT);
884 #elif defined(__APPLE__)
885     errno= SOCKET_ETIMEDOUT;
886 #else
887 #error Oops...Wrong OS
888 #endif
889 
890   /* Error or timeout? */
891   if (ret <= 0)
892     DBUG_RETURN(ret);
893 
894   /* The requested I/O event is ready? */
895   switch (event)
896   {
897   case VIO_IO_EVENT_READ:
898     ret= MY_TEST(FD_ISSET(fd, &readfds));
899     break;
900   case VIO_IO_EVENT_WRITE:
901   case VIO_IO_EVENT_CONNECT:
902     ret= MY_TEST(FD_ISSET(fd, &writefds));
903     break;
904   }
905 
906   /* Error conditions pending? */
907   ret|= MY_TEST(FD_ISSET(fd, &exceptfds));
908 
909   /* Not a timeout, ensure that a condition was met. */
910   assert(ret);
911 
912   DBUG_RETURN(ret);
913 }
914 
915 #endif /* _WIN32 */
916 
917 
918 /**
919   Connect to a peer address.
920 
921   @param vio       A VIO object.
922   @param addr      Socket address containing the peer address.
923   @param len       Length of socket address.
924   @param timeout   Interval (in milliseconds) to wait until a
925                    connection is established.
926 
927   @retval FALSE   A connection was successfully established.
928   @retval TRUE    A fatal error. See socket_errno.
929 */
930 
931 my_bool
vio_socket_connect(Vio * vio,struct sockaddr * addr,socklen_t len,int timeout)932 vio_socket_connect(Vio *vio, struct sockaddr *addr, socklen_t len, int timeout)
933 {
934   int ret, wait;
935   DBUG_ENTER("vio_socket_connect");
936 
937   /* Only for socket-based transport types. */
938   assert(vio->type == VIO_TYPE_SOCKET || vio->type == VIO_TYPE_TCPIP);
939 
940   /* If timeout is not infinite, set socket to non-blocking mode. */
941   if ((timeout > -1) && vio_set_blocking(vio, FALSE))
942     DBUG_RETURN(TRUE);
943 
944   /* Initiate the connection. */
945   ret= mysql_socket_connect(vio->mysql_socket, addr, len);
946 
947 #ifdef _WIN32
948   wait= (ret == SOCKET_ERROR) &&
949         (WSAGetLastError() == WSAEINPROGRESS ||
950          WSAGetLastError() == WSAEWOULDBLOCK);
951 #else
952   wait= (ret == -1) && (errno == EINPROGRESS || errno == EALREADY);
953 #endif
954 
955   /*
956     The connection is in progress. The vio_io_wait() call can be used
957     to wait up to a specified period of time for the connection to
958     succeed.
959 
960     If vio_io_wait() returns 0 (after waiting however many seconds),
961     the socket never became writable (host is probably unreachable.)
962     Otherwise, if vio_io_wait() returns 1, then one of two conditions
963     exist:
964 
965     1. An error occurred. Use getsockopt() to check for this.
966     2. The connection was set up successfully: getsockopt() will
967        return 0 as an error.
968   */
969   if (wait && (vio_io_wait(vio, VIO_IO_EVENT_CONNECT, timeout) == 1))
970   {
971     int error;
972     IF_WIN(int, socklen_t) optlen= sizeof(error);
973     IF_WIN(char, void) *optval= (IF_WIN(char, void) *) &error;
974 
975     /*
976       At this point, we know that something happened on the socket.
977       But this does not means that everything is alright. The connect
978       might have failed. We need to retrieve the error code from the
979       socket layer. We must return success only if we are sure that
980       it was really a success. Otherwise we might prevent the caller
981       from trying another address to connect to.
982     */
983     if (!(ret= mysql_socket_getsockopt(vio->mysql_socket, SOL_SOCKET, SO_ERROR, optval, &optlen)))
984     {
985 #ifdef _WIN32
986       WSASetLastError(error);
987 #else
988       errno= error;
989 #endif
990       ret= MY_TEST(error);
991     }
992   }
993 
994   /* If necessary, restore the blocking mode, but only if connect succeeded. */
995   if ((timeout > -1) && (ret == 0))
996   {
997     if (vio_set_blocking(vio, TRUE))
998       DBUG_RETURN(TRUE);
999   }
1000 
1001   DBUG_RETURN(MY_TEST(ret));
1002 }
1003 
1004 
1005 /**
1006   Determine if the endpoint of a connection is still available.
1007 
1008   @remark The socket is assumed to be disconnected if an EOF
1009           condition is encountered.
1010 
1011   @param vio      The VIO object.
1012 
1013   @retval TRUE    EOF condition not found.
1014   @retval FALSE   EOF condition is signaled.
1015 */
1016 
vio_is_connected(Vio * vio)1017 my_bool vio_is_connected(Vio *vio)
1018 {
1019   uint bytes= 0;
1020   DBUG_ENTER("vio_is_connected");
1021 
1022   /*
1023     The first step of detecting an EOF condition is verifying
1024     whether there is data to read. Data in this case would be
1025     the EOF. An exceptional condition event and/or errors are
1026     interpreted as if there is data to read.
1027   */
1028   if (!vio_io_wait(vio, VIO_IO_EVENT_READ, 0))
1029     DBUG_RETURN(TRUE);
1030 
1031   /*
1032     The second step is read() or recv() from the socket returning
1033     0 (EOF). Unfortunately, it's not possible to call read directly
1034     as we could inadvertently read meaningful connection data.
1035     Simulate a read by retrieving the number of bytes available to
1036     read -- 0 meaning EOF. In the presence of unrecoverable errors,
1037     the socket is assumed to be disconnected.
1038   */
1039   while (socket_peek_read(vio, &bytes))
1040   {
1041     if (socket_errno != SOCKET_EINTR)
1042       DBUG_RETURN(FALSE);
1043   }
1044 
1045 #ifdef HAVE_OPENSSL
1046   /* There might be buffered data at the SSL layer. */
1047   if (!bytes && vio->type == VIO_TYPE_SSL)
1048     bytes= SSL_pending((SSL*) vio->ssl_arg);
1049 #endif
1050 
1051   DBUG_RETURN(bytes ? TRUE : FALSE);
1052 }
1053 
1054 #ifndef NDEBUG
1055 
1056 /**
1057   Number of bytes in the read or socket buffer
1058 
1059   @remark An EOF condition might count as one readable byte.
1060 
1061   @return number of bytes in one of the buffers or < 0 if error.
1062 */
1063 
vio_pending(Vio * vio)1064 ssize_t vio_pending(Vio *vio)
1065 {
1066   uint bytes= 0;
1067 
1068   /* Data pending on the read buffer. */
1069   if (vio->read_pos < vio->read_end)
1070     return vio->read_end - vio->read_pos;
1071 
1072   /* Skip non-socket based transport types. */
1073   if (vio->type == VIO_TYPE_TCPIP || vio->type == VIO_TYPE_SOCKET)
1074   {
1075     /* Obtain number of readable bytes in the socket buffer. */
1076     if (socket_peek_read(vio, &bytes))
1077       return -1;
1078   }
1079 
1080   return (ssize_t) bytes;
1081 }
1082 
1083 #endif
1084 
1085 /**
1086   Checks if the error code, returned by vio_getnameinfo(), means it was the
1087   "No-name" error.
1088 
1089   Windows-specific note: getnameinfo() returns WSANO_DATA instead of
1090   EAI_NODATA or EAI_NONAME when no reverse mapping is available at the host
1091   (i.e. Windows can't get hostname by IP-address). This error should be
1092   treated as EAI_NONAME.
1093 
1094   @return if the error code is actually EAI_NONAME.
1095   @retval true if the error code is EAI_NONAME.
1096   @retval false otherwise.
1097 */
1098 
vio_is_no_name_error(int err_code)1099 my_bool vio_is_no_name_error(int err_code)
1100 {
1101 #ifdef _WIN32
1102 
1103   return err_code == WSANO_DATA || err_code == EAI_NONAME;
1104 
1105 #else
1106 
1107   return err_code == EAI_NONAME;
1108 
1109 #endif
1110 }
1111 
1112 
1113 /**
1114   This is a wrapper for the system getnameinfo(), because different OS
1115   differ in the getnameinfo() implementation:
1116     - Solaris 10 requires that the 2nd argument (salen) must match the
1117       actual size of the struct sockaddr_storage passed to it;
1118     - Mac OS X has sockaddr_in::sin_len and sockaddr_in6::sin6_len and
1119       requires them to be filled.
1120 */
1121 
vio_getnameinfo(const struct sockaddr * sa,char * hostname,size_t hostname_size,char * port,size_t port_size,int flags)1122 int vio_getnameinfo(const struct sockaddr *sa,
1123                     char *hostname, size_t hostname_size,
1124                     char *port, size_t port_size,
1125                     int flags)
1126 {
1127   int sa_length= 0;
1128 
1129   switch (sa->sa_family) {
1130   case AF_INET:
1131     sa_length= sizeof (struct sockaddr_in);
1132 #ifdef HAVE_SOCKADDR_IN_SIN_LEN
1133     ((struct sockaddr_in *) sa)->sin_len= sa_length;
1134 #endif /* HAVE_SOCKADDR_IN_SIN_LEN */
1135     break;
1136 
1137 #ifdef HAVE_IPV6
1138   case AF_INET6:
1139     sa_length= sizeof (struct sockaddr_in6);
1140 # ifdef HAVE_SOCKADDR_IN6_SIN6_LEN
1141     ((struct sockaddr_in6 *) sa)->sin6_len= sa_length;
1142 # endif /* HAVE_SOCKADDR_IN6_SIN6_LEN */
1143     break;
1144 #endif /* HAVE_IPV6 */
1145   }
1146 
1147   return getnameinfo(sa, sa_length,
1148                      hostname, hostname_size,
1149                      port, port_size,
1150                      flags);
1151 }
1152