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