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