1 /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003  Brian Bruns
3  * Copyright (C) 2004-2015  Ziglio Frediano
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library 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 GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 
21 #include <config.h>
22 
23 #include <stdarg.h>
24 #include <stdio.h>
25 
26 #include <freetds/time.h>
27 
28 #if HAVE_SYS_TYPES_H
29 #include <sys/types.h>
30 #endif /* HAVE_SYS_TYPES_H */
31 
32 #if HAVE_ERRNO_H
33 #include <errno.h>
34 #endif /* HAVE_ERRNO_H */
35 
36 #if HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif /* HAVE_UNISTD_H */
39 
40 #if HAVE_STDLIB_H
41 #include <stdlib.h>
42 #endif /* HAVE_STDLIB_H */
43 
44 #if HAVE_STRING_H
45 #include <string.h>
46 #endif /* HAVE_STRING_H */
47 
48 #if HAVE_SYS_SOCKET_H
49 #include <sys/socket.h>
50 #endif /* HAVE_SYS_SOCKET_H */
51 
52 #if HAVE_NETINET_IN_H
53 #include <netinet/in.h>
54 #endif /* HAVE_NETINET_IN_H */
55 
56 #if HAVE_NETINET_TCP_H
57 #include <netinet/tcp.h>
58 #endif /* HAVE_NETINET_TCP_H */
59 
60 #if HAVE_ARPA_INET_H
61 #include <arpa/inet.h>
62 #endif /* HAVE_ARPA_INET_H */
63 
64 #if HAVE_SYS_IOCTL_H
65 #include <sys/ioctl.h>
66 #endif /* HAVE_SYS_IOCTL_H */
67 
68 #if HAVE_SELECT_H
69 #include <sys/select.h>
70 #endif /* HAVE_SELECT_H */
71 
72 #if HAVE_POLL_H
73 #include <poll.h>
74 #endif /* HAVE_POLL_H */
75 
76 #if HAVE_FCNTL_H
77 #include <fcntl.h>
78 #endif /* HAVE_FCNTL_H */
79 
80 #ifdef HAVE_SYS_EVENTFD_H
81 #include <sys/eventfd.h>
82 #endif /* HAVE_SYS_EVENTFD_H */
83 
84 #ifdef _WIN32
85 #include <winsock2.h>
86 #include <ws2tcpip.h>
87 #include <mstcpip.h>
88 #endif
89 
90 #include <freetds/tds.h>
91 #include <freetds/utils/string.h>
92 #include <freetds/tls.h>
93 #include <freetds/replacements.h>
94 
95 #include <signal.h>
96 #include <assert.h>
97 
98 /* error is always returned */
99 #define TDSSELERR   0
100 #define TDSPOLLURG 0x8000u
101 
102 #if ENABLE_ODBC_MARS
103 static void tds_check_cancel(TDSCONNECTION *conn);
104 #endif
105 
106 
107 /**
108  * \addtogroup network
109  * @{
110  */
111 
112 #ifdef _WIN32
113 int
tds_socket_init(void)114 tds_socket_init(void)
115 {
116 	WSADATA wsadata;
117 
118 	return WSAStartup(MAKEWORD(2, 2), &wsadata);
119 }
120 
121 void
tds_socket_done(void)122 tds_socket_done(void)
123 {
124 	WSACleanup();
125 }
126 #endif
127 
128 #if !defined(SOL_TCP) && (defined(IPPROTO_TCP) || defined(_WIN32))
129 /* fix incompatibility between MS headers */
130 # ifndef IPPROTO_TCP
131 #  define IPPROTO_TCP IPPROTO_TCP
132 # endif
133 # define SOL_TCP IPPROTO_TCP
134 #endif
135 
136 /* Optimize the way we send packets */
137 #undef USE_CORK
138 #undef USE_NODELAY
139 /* On early Linux use TCP_CORK if available */
140 #if defined(__linux__) && defined(TCP_CORK)
141 #define USE_CORK 1
142 /* On *BSD try to use TCP_CORK */
143 /*
144  * NOPUSH flag do not behave in the same way
145  * cf ML "FreeBSD 5.0 performance problems with TCP_NOPUSH"
146  */
147 #elif (defined(__FreeBSD__) || defined(__GNU_FreeBSD__) || defined(__OpenBSD__)) && defined(TCP_CORK)
148 #define USE_CORK 1
149 /* otherwise use NODELAY */
150 #elif defined(TCP_NODELAY) && defined(SOL_TCP)
151 #define USE_NODELAY 1
152 /* under VMS we have to define TCP_NODELAY */
153 #elif defined(__VMS)
154 #define TCP_NODELAY 1
155 #define USE_NODELAY 1
156 #endif
157 
158 #ifndef __APPLE__
159 #undef SO_NOSIGPIPE
160 #endif
161 
162 /**
163  * Set socket to non-blocking
164  * @param sock socket to set
165  * @return 0 on success or error code
166  */
167 int
tds_socket_set_nonblocking(TDS_SYS_SOCKET sock)168 tds_socket_set_nonblocking(TDS_SYS_SOCKET sock)
169 {
170 #if !defined(_WIN32)
171 	unsigned int ioctl_nonblocking = 1;
172 #else
173 	u_long ioctl_nonblocking = 1;
174 #endif
175 
176 	if (IOCTLSOCKET(sock, FIONBIO, &ioctl_nonblocking) >= 0)
177 		return 0;
178 	return sock_errno;
179 }
180 
181 static void
tds_addrinfo_set_port(struct addrinfo * addr,unsigned int port)182 tds_addrinfo_set_port(struct addrinfo *addr, unsigned int port)
183 {
184 	assert(addr != NULL);
185 
186 	switch(addr->ai_family) {
187 	case AF_INET:
188 		((struct sockaddr_in *) addr->ai_addr)->sin_port = htons(port);
189 		break;
190 
191 #ifdef AF_INET6
192 	case AF_INET6:
193 		((struct sockaddr_in6 *) addr->ai_addr)->sin6_port = htons(port);
194 		break;
195 #endif
196 	}
197 }
198 
199 const char*
tds_addrinfo2str(struct addrinfo * addr,char * name,int namemax)200 tds_addrinfo2str(struct addrinfo *addr, char *name, int namemax)
201 {
202 #ifndef NI_NUMERICHOST
203 #define NI_NUMERICHOST 0
204 #endif
205 	if (!name || namemax <= 0)
206 		return "";
207 	if (getnameinfo(addr->ai_addr, addr->ai_addrlen, name, namemax, NULL, 0, NI_NUMERICHOST) == 0)
208 		return name;
209 	name[0] = 0;
210 	return name;
211 }
212 
213 /**
214  * Returns error stored in the socket
215  */
216 static int
tds_get_socket_error(TDS_SYS_SOCKET sock)217 tds_get_socket_error(TDS_SYS_SOCKET sock)
218 {
219 	int err;
220 	SOCKLEN_T optlen = sizeof(err);
221 	char *errstr;
222 
223 	/* check socket error */
224 	if (tds_getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) != 0) {
225 		err = sock_errno;
226 		errstr = sock_strerror(err);
227 		tdsdump_log(TDS_DBG_ERROR, "getsockopt(2) failed: %s\n", errstr);
228 		sock_strerror_free(errstr);
229 	} else if (err != 0) {
230 		errstr = sock_strerror(err);
231 		tdsdump_log(TDS_DBG_ERROR, "getsockopt(2) reported: %s\n", errstr);
232 		sock_strerror_free(errstr);
233 	}
234 	return err;
235 }
236 
237 /**
238  * Setup the socket and attempt a connection.
239  * Function allocate the socket in *p_sock and try to start a connection.
240  * @param p_sock where returned socket is stored. Socket is stored even on error.
241  *        Can be INVALID_SOCKET.
242  * @param addr address to use for attempting the connection
243  * @param port port to connect to
244  * @param p_oserr where system error is returned
245  * @returns TDSEOK is success, TDSEINPROGRESS if connection attempt is started
246  *          or any other error.
247  */
248 static TDSERRNO
tds_setup_socket(TDS_SYS_SOCKET * p_sock,struct addrinfo * addr,unsigned int port,int * p_oserr)249 tds_setup_socket(TDS_SYS_SOCKET *p_sock, struct addrinfo *addr, unsigned int port, int *p_oserr)
250 {
251 	enum {
252 		TDS_SOCKET_KEEPALIVE_IDLE = 40,
253 		TDS_SOCKET_KEEPALIVE_INTERVAL = 2
254 	};
255 	TDS_SYS_SOCKET sock;
256 	char ipaddr[128];
257 	int retval, len, err;
258 	char *errstr;
259 #if defined(_WIN32)
260 	struct tcp_keepalive keepalive = {
261 		TRUE,
262 		TDS_SOCKET_KEEPALIVE_IDLE * 1000,
263 		TDS_SOCKET_KEEPALIVE_INTERVAL * 1000
264 	};
265 	DWORD written;
266 #endif
267 
268 	*p_oserr = 0;
269 
270 	tds_addrinfo_set_port(addr, port);
271 	tds_addrinfo2str(addr, ipaddr, sizeof(ipaddr));
272 
273 	*p_sock = sock = socket(addr->ai_family, SOCK_STREAM, 0);
274 	if (TDS_IS_SOCKET_INVALID(sock)) {
275 		errstr = sock_strerror(*p_oserr = sock_errno);
276 		tdsdump_log(TDS_DBG_ERROR, "socket creation error: %s\n", errstr);
277 		sock_strerror_free(errstr);
278 		return TDSESOCK;
279 	}
280 
281 #ifdef SO_KEEPALIVE
282 	len = 1;
283 	setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (const void *) &len, sizeof(len));
284 #endif
285 
286 #if defined(_WIN32)
287 	if (WSAIoctl(sock, SIO_KEEPALIVE_VALS, &keepalive, sizeof(keepalive),
288 		     NULL, 0, &written, NULL, NULL) != 0) {
289 		errstr = sock_strerror(*p_oserr = sock_errno);
290 		tdsdump_log(TDS_DBG_ERROR, "error setting keepalive: %s\n", errstr);
291 		sock_strerror_free(errstr);
292 	}
293 #elif defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
294 	len = TDS_SOCKET_KEEPALIVE_IDLE;
295 	setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, (const void *) &len, sizeof(len));
296 	len = TDS_SOCKET_KEEPALIVE_INTERVAL;
297 	setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, (const void *) &len, sizeof(len));
298 #endif
299 
300 #if defined(SO_NOSIGPIPE)
301 	len = 1;
302 	if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (const void *) &len, sizeof(len))) {
303 		*p_oserr = sock_errno;
304 		return TDSESOCK;
305 	}
306 #endif
307 
308 	len = 1;
309 #if defined(USE_NODELAY)
310 	setsockopt(sock, SOL_TCP, TCP_NODELAY, (const void *) &len, sizeof(len));
311 #elif defined(USE_CORK)
312 	setsockopt(sock, SOL_TCP, TCP_NODELAY, (const void *) &len, sizeof(len));
313 	setsockopt(sock, SOL_TCP, TCP_CORK, (const void *) &len, sizeof(len));
314 #else
315 #error One should be defined
316 #endif
317 
318 	tdsdump_log(TDS_DBG_INFO1, "Connecting to %s port %d\n", ipaddr, port);
319 
320 #ifdef  DOS32X			/* the other connection doesn't work  on WATTCP32 */
321 	if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) {
322 		*p_oserr = sock_errno;
323 		tdsdump_log(TDS_DBG_ERROR, "tds_setup_socket(): %s:%d", ipaddr, port);
324 		return TDSECONN;
325 	}
326 	return TDSEOK;
327 #else
328 	if ((*p_oserr = tds_socket_set_nonblocking(sock)) != 0) {
329 		return TDSEUSCT; 	/* close enough: "Unable to set communications timer" */
330 	}
331 	retval = connect(sock, addr->ai_addr, addr->ai_addrlen);
332 	if (retval == 0) {
333 		tdsdump_log(TDS_DBG_INFO2, "connection established\n");
334 		return TDSEOK;
335 	}
336 
337 	/* got some kind of error */
338 	err = *p_oserr = sock_errno;
339 	errstr = sock_strerror(err);
340 	tdsdump_log(TDS_DBG_ERROR, "tds_setup_socket: connect(2) returned \"%s\"\n", errstr);
341 	sock_strerror_free(errstr);
342 
343 	/* connection attempt started */
344 	if (err == TDSSOCK_EINPROGRESS)
345 		return TDSEINPROGRESS;
346 
347 #if DEBUGGING_CONNECTING_PROBLEM
348 	if (err != ECONNREFUSED && err != ENETUNREACH) {
349 		tdsdump_dump_buf(TDS_DBG_ERROR, "Contents of sockaddr_in", addr->ai_addr, addr->ai_addrlen);
350 		tdsdump_log(TDS_DBG_ERROR, 	" sockaddr_in:\t"
351 						      "%s = %x\n"
352 						"\t\t\t%s = %x\n"
353 						"\t\t\t%s = %s\n"
354 						, "sin_family", addr->ai_family
355 						, "port", port
356 						, "address", ipaddr
357 						);
358 	}
359 #endif
360 	return TDSECONN;
361 #endif	/* not DOS32X */
362 }
363 
364 typedef struct {
365 	struct addrinfo *addr;
366 	unsigned next_retry_time;
367 	unsigned retry_count;
368 } retry_addr;
369 
370 TDSERRNO
tds_open_socket(TDSSOCKET * tds,struct addrinfo * addr,unsigned int port,int timeout,int * p_oserr)371 tds_open_socket(TDSSOCKET *tds, struct addrinfo *addr, unsigned int port, int timeout, int *p_oserr)
372 {
373 	TDSCONNECTION *conn = tds->conn;
374 	int len, i;
375 	TDSERRNO tds_error;
376 	struct addrinfo *curr_addr;
377 	struct pollfd *fds;
378 	retry_addr *addresses;
379 	unsigned curr_time, start_time;
380 	typedef struct {
381 		retry_addr retry;
382 		struct pollfd fd;
383 	} alloc_addr;
384 	enum { MAX_RETRY = 10 };
385 
386 	*p_oserr = 0;
387 
388 	if (!addr)
389 		return TDSECONN;
390 
391 	tdsdump_log(TDS_DBG_INFO1, "Connecting with protocol version %d.%d\n",
392 		    TDS_MAJOR(conn), TDS_MINOR(conn));
393 
394 	for (len = 0, curr_addr = addr; curr_addr != NULL; curr_addr = curr_addr->ai_next)
395 		++len;
396 
397 	addresses = (retry_addr *) tds_new0(alloc_addr, len);
398 	if (!addresses)
399 		return TDSEMEM;
400 	fds = (struct pollfd *) &addresses[len];
401 
402 	tds_error = TDSECONN;
403 
404 	/* fill all structures */
405 	curr_time = start_time = tds_gettime_ms();
406 	for (len = 0, curr_addr = addr; curr_addr != NULL; curr_addr = curr_addr->ai_next) {
407 		fds[len].fd = INVALID_SOCKET;
408 		addresses[len].addr = curr_addr;
409 		addresses[len].next_retry_time = curr_time;
410 		addresses[len].retry_count = 0;
411 		++len;
412 	}
413 
414 	/* if we have only one address means that availability groups feature is not
415 	 * present, avoid to check the addresses multiple times */
416 	if (len == 1)
417 		addresses[0].retry_count = MAX_RETRY;
418 
419 	timeout *= 1000;
420 	if (!timeout) {
421 		/* A timeout of zero means wait forever */
422 		timeout = -1;
423 	}
424 
425 	/* now the list is full with sockets trying to connect */
426 	while (len) {
427 		int rc, poll_timeout = timeout;
428 
429 		/* timeout */
430 		if (poll_timeout >= 0) {
431 			if (curr_time - start_time > (unsigned) poll_timeout) {
432 				*p_oserr = TDSSOCK_ETIMEDOUT;
433 				goto exit;
434 			}
435 			poll_timeout -= curr_time - start_time;
436 		}
437 
438 		/* try again if needed */
439 		for (i = 0; i < len; ++i) {
440 			int time_left;
441 
442 			if (!TDS_IS_SOCKET_INVALID(fds[i].fd))
443 				continue;
444 			time_left = addresses[i].next_retry_time - curr_time;
445 			if (time_left <= 0) {
446 				TDS_SYS_SOCKET sock;
447 				tds_error = tds_setup_socket(&sock, addresses[i].addr, port, p_oserr);
448 				switch (tds_error) {
449 				case TDSEOK:
450 					/* connected! */
451 					/* free other sockets and continue with this one */
452 					conn->s = sock;
453 					tds_error = TDSEOK;
454 					goto exit;
455 				case TDSEINPROGRESS:
456 					/* save socket in the list */
457 					fds[i].fd = sock;
458 					break;
459 				default:
460 					/* error, continue with other addresses */
461 					if (!TDS_IS_SOCKET_INVALID(sock))
462 						CLOSESOCKET(sock);
463 					--len;
464 					fds[i] = fds[len];
465 					addresses[i] = addresses[len];
466 					--i;
467 					continue;
468 				}
469 			} else {
470 				/* update timeout */
471 				if (time_left < poll_timeout || poll_timeout < 0)
472 					poll_timeout = time_left;
473 			}
474 		}
475 
476 		/* wait activities on file descriptors */
477 		for (i = 0; i < len; ++i) {
478 			fds[i].revents = 0;
479 			fds[i].events = TDSSELWRITE|TDSSELERR;
480 		}
481 		tds_error = TDSECONN;
482 		rc = poll(fds, len, poll_timeout);
483 		i = sock_errno; /* save to avoid overrides */
484 		curr_time = tds_gettime_ms();
485 
486 		/* error */
487 		if (rc < 0) {
488 			*p_oserr = i;
489 			if (*p_oserr == TDSSOCK_EINTR)
490 				continue;
491 			goto exit;
492 		}
493 
494 		/* got some event on file descriptors */
495 		for (i = 0; i < len; ++i) {
496 			if (TDS_IS_SOCKET_INVALID(fds[i].fd))
497 				continue;
498 			if (!fds[i].revents)
499 				continue;
500 			*p_oserr = tds_get_socket_error(fds[i].fd);
501 			if (*p_oserr || (fds[i].revents & POLLERR) != 0) {
502 				/* error, remove from list and possibly make
503 				 * the loop exit */
504 				CLOSESOCKET(fds[i].fd);
505 				fds[i].fd = INVALID_SOCKET;
506 				addresses[i].next_retry_time = curr_time + 1000;
507 				if (++addresses[i].retry_count >= MAX_RETRY || len == 1) {
508 					--len;
509 					fds[i] = fds[len];
510 					addresses[i] = addresses[len];
511 					--i;
512 				}
513 				continue;
514 			}
515 			if (fds[i].revents & POLLOUT) {
516 				conn->s = fds[i].fd;
517 				fds[i].fd = INVALID_SOCKET;
518 				tds_error = TDSEOK;
519 				goto exit;
520 			}
521 		}
522 	}
523 
524 exit:
525 	if (tds_error != TDSEOK) {
526 		tdsdump_log(TDS_DBG_ERROR, "tds_open_socket() failed\n");
527 	} else {
528 		tdsdump_log(TDS_DBG_INFO2, "tds_open_socket() succeeded\n");
529 		tds->state = TDS_IDLE;
530 	}
531 
532 	while (--len >= 0) {
533 		if (!TDS_IS_SOCKET_INVALID(fds[len].fd))
534 			CLOSESOCKET(fds[len].fd);
535 	}
536 	free(addresses);
537 	return tds_error;
538 }
539 
540 /**
541  * Close current socket.
542  * For last socket close entire connection.
543  * For MARS send FIN request.
544  * This attempts a graceful disconnection, for ungraceful call
545  * tds_connection_close.
546  */
547 void
tds_close_socket(TDSSOCKET * tds)548 tds_close_socket(TDSSOCKET * tds)
549 {
550 	if (!IS_TDSDEAD(tds)) {
551 #if ENABLE_ODBC_MARS
552 		TDSCONNECTION *conn = tds->conn;
553 		unsigned n = 0, count = 0;
554 		tds_mutex_lock(&conn->list_mtx);
555 		for (; n < conn->num_sessions; ++n)
556 			if (TDSSOCKET_VALID(conn->sessions[n]))
557 				++count;
558 		if (count > 1)
559 			tds_append_fin(tds);
560 		tds_mutex_unlock(&conn->list_mtx);
561 		if (count <= 1) {
562 			tds_disconnect(tds);
563 			tds_connection_close(conn);
564 		} else {
565 			tds_set_state(tds, TDS_DEAD);
566 		}
567 #else
568 		tds_disconnect(tds);
569 		tds_ssl_deinit(tds->conn);
570 		if (!TDS_IS_SOCKET_INVALID(tds_get_s(tds)) && CLOSESOCKET(tds_get_s(tds)) == -1)
571 			tdserror(tds_get_ctx(tds), tds,  TDSECLOS, sock_errno);
572 		tds_set_s(tds, INVALID_SOCKET);
573 		tds_set_state(tds, TDS_DEAD);
574 #endif
575 	}
576 }
577 
578 void
tds_connection_close(TDSCONNECTION * conn)579 tds_connection_close(TDSCONNECTION *conn)
580 {
581 #if ENABLE_ODBC_MARS
582 	unsigned n = 0;
583 #endif
584 
585 	tds_ssl_deinit(conn);
586 	if (!TDS_IS_SOCKET_INVALID(conn->s)) {
587 		/* TODO check error ?? how to return it ?? */
588 		CLOSESOCKET(conn->s);
589 		conn->s = INVALID_SOCKET;
590 	}
591 
592 #if ENABLE_ODBC_MARS
593 	tds_mutex_lock(&conn->list_mtx);
594 	for (; n < conn->num_sessions; ++n)
595 		if (TDSSOCKET_VALID(conn->sessions[n]))
596 			tds_set_state(conn->sessions[n], TDS_DEAD);
597 	tds_mutex_unlock(&conn->list_mtx);
598 #else
599 	tds_set_state((TDSSOCKET* ) conn, TDS_DEAD);
600 #endif
601 }
602 
603 /**
604  * Select on a socket until it's available or the timeout expires.
605  * Meanwhile, call the interrupt function.
606  * \return	>0 ready descriptors
607  *		 0 timeout
608  * 		<0 error (cf. errno).  Caller should  close socket and return failure.
609  * This function does not call tdserror or close the socket because it can't know the context in which it's being called.
610  */
611 int
tds_select(TDSSOCKET * tds,unsigned tds_sel,int timeout_seconds)612 tds_select(TDSSOCKET * tds, unsigned tds_sel, int timeout_seconds)
613 {
614 	int rc, seconds;
615 	unsigned int poll_seconds;
616 
617 	assert(tds != NULL);
618 	assert(timeout_seconds >= 0);
619 
620 	/*
621 	 * The select loop.
622 	 * If an interrupt handler is installed, we iterate once per second,
623 	 * 	else we try once, timing out after timeout_seconds (0 == never).
624 	 * If select(2) is interrupted by a signal (e.g. press ^C in sqsh), we timeout.
625 	 * 	(The application can retry if desired by installing a signal handler.)
626 	 *
627 	 * We do not measure current time against end time, to avoid being tricked by ntpd(8) or similar.
628 	 * Instead, we just count down.
629 	 *
630 	 * We exit on the first of these events:
631 	 * 1.  a descriptor is ready. (return to caller)
632 	 * 2.  select(2) returns an important error.  (return to caller)
633 	 * A timeout of zero says "wait forever".  We do that by passing a NULL timeval pointer to select(2).
634 	 */
635 	poll_seconds = (tds_get_ctx(tds) && tds_get_ctx(tds)->int_handler)? 1 : timeout_seconds;
636 	for (seconds = timeout_seconds; timeout_seconds == 0 || seconds > 0; seconds -= poll_seconds) {
637 		struct pollfd fds[2];
638 		int timeout = poll_seconds ? poll_seconds * 1000 : -1;
639 
640 		if (TDS_IS_SOCKET_INVALID(tds_get_s(tds)))
641 			return -1;
642 
643 		if ((tds_sel & TDSSELREAD) != 0 && tds->conn->tls_session && tds_ssl_pending(tds->conn))
644 			return POLLIN;
645 
646 		fds[0].fd = tds_get_s(tds);
647 		fds[0].events = tds_sel;
648 		fds[0].revents = 0;
649 		fds[1].fd = tds_wakeup_get_fd(&tds->conn->wakeup);
650 		fds[1].events = POLLIN;
651 		fds[1].revents = 0;
652 		rc = poll(fds, 2, timeout);
653 
654 		if (rc > 0 ) {
655 			if (fds[0].revents & POLLERR) {
656 				set_sock_errno(TDSSOCK_ECONNRESET);
657 				return -1;
658 			}
659 			rc = fds[0].revents;
660 			if (fds[1].revents) {
661 #if ENABLE_ODBC_MARS
662 				tds_check_cancel(tds->conn);
663 #endif
664 				rc |= TDSPOLLURG;
665 			}
666 			return rc;
667 		}
668 
669 		if (rc < 0) {
670 			char *errstr;
671 
672 			switch (sock_errno) {
673 			case TDSSOCK_EINTR:
674 				/* FIXME this should be global maximun, not loop one */
675 				seconds += poll_seconds;
676 				break;	/* let interrupt handler be called */
677 			default: /* documented: EFAULT, EBADF, EINVAL */
678 				errstr = sock_strerror(sock_errno);
679 				tdsdump_log(TDS_DBG_ERROR, "error: poll(2) returned %d, \"%s\"\n",
680 						sock_errno, errstr);
681 				sock_strerror_free(errstr);
682 				return rc;
683 			}
684 		}
685 
686 		assert(rc == 0 || (rc < 0 && sock_errno == TDSSOCK_EINTR));
687 
688 		if (tds_get_ctx(tds) && tds_get_ctx(tds)->int_handler) {	/* interrupt handler installed */
689 			/*
690 			 * "If hndlintr() returns INT_CANCEL, DB-Library sends an attention token [TDS_BUFSTAT_ATTN]
691 			 * to the server. This causes the server to discontinue command processing.
692 			 * The server may send additional results that have already been computed.
693 			 * When control returns to the mainline code, the mainline code should do
694 			 * one of the following:
695 			 * - Flush the results using dbcancel
696 			 * - Process the results normally"
697 			 */
698 			int timeout_action = (*tds_get_ctx(tds)->int_handler) (tds_get_parent(tds));
699 			switch (timeout_action) {
700 			case TDS_INT_CONTINUE:		/* keep waiting */
701 				continue;
702 			case TDS_INT_CANCEL:		/* abort the current command batch */
703 							/* FIXME tell tds_goodread() not to call tdserror() */
704 				return 0;
705 			default:
706 				tdsdump_log(TDS_DBG_NETWORK,
707 					"tds_select: invalid interupt handler return code: %d\n", timeout_action);
708 				return -1;
709 			}
710 		}
711 		/*
712 		 * We can reach here if no interrupt handler was installed and we either timed out or got EINTR.
713 		 * We cannot be polling, so we are about to drop out of the loop.
714 		 */
715 		assert(poll_seconds == timeout_seconds);
716 	}
717 
718 	return 0;
719 }
720 
721 /**
722  * Read from an OS socket
723  * @TODO remove tds, save error somewhere, report error in another way
724  * @returns 0 if blocking, <0 error >0 bytes read
725  */
726 static int
tds_socket_read(TDSCONNECTION * conn,TDSSOCKET * tds,unsigned char * buf,int buflen)727 tds_socket_read(TDSCONNECTION * conn, TDSSOCKET *tds, unsigned char *buf, int buflen)
728 {
729 	int len, err;
730 
731 #if ENABLE_EXTRA_CHECKS
732 	/* this simulate the fact that recv can return less bytes */
733 	if (buflen >= 5) {
734 		static int cnt = 0;
735 		if (++cnt == 5) {
736 			cnt = 0;
737 			buflen -= 3;
738 		}
739 	}
740 #endif
741 
742 	/* read directly from socket*/
743 	len = READSOCKET(conn->s, buf, buflen);
744 	if (len > 0)
745 		return len;
746 
747 	err = sock_errno;
748 	if (len < 0 && TDSSOCK_WOULDBLOCK(err))
749 		return 0;
750 
751 	/* detect connection close */
752 	tds_connection_close(conn);
753 	tdserror(conn->tds_ctx, tds, len == 0 ? TDSESEOF : TDSEREAD, len == 0 ? 0 : err);
754 	return -1;
755 }
756 
757 /**
758  * Write to an OS socket
759  * @returns 0 if blocking, <0 error >0 bytes readed
760  */
761 static int
tds_socket_write(TDSCONNECTION * conn,TDSSOCKET * tds,const unsigned char * buf,int buflen)762 tds_socket_write(TDSCONNECTION *conn, TDSSOCKET *tds, const unsigned char *buf, int buflen)
763 {
764 	int err, len;
765 	char *errstr;
766 
767 #if ENABLE_EXTRA_CHECKS
768 	/* this simulate the fact that send can return less bytes */
769 	if (buflen >= 11) {
770 		static int cnt = 0;
771 		if (++cnt == 5) {
772 			cnt = 0;
773 			buflen -= 3;
774 		}
775 	}
776 #endif
777 
778 #if defined(SO_NOSIGPIPE)
779 	len = send(conn->s, buf, buflen, 0);
780 #else
781 	len = WRITESOCKET(conn->s, buf, buflen);
782 #endif
783 	if (len > 0)
784 		return len;
785 
786 	err = sock_errno;
787 	if (0 == len || TDSSOCK_WOULDBLOCK(err) || err == TDSSOCK_EINTR)
788 		return 0;
789 
790 	assert(len < 0);
791 
792 	/* detect connection close */
793 	errstr = sock_strerror(err);
794 	tdsdump_log(TDS_DBG_NETWORK, "send(2) failed: %d (%s)\n", err, errstr);
795 	sock_strerror_free(errstr);
796 	tds_connection_close(conn);
797 	tdserror(conn->tds_ctx, tds, TDSEWRIT, err);
798 	return -1;
799 }
800 
801 int
tds_wakeup_init(TDSPOLLWAKEUP * wakeup)802 tds_wakeup_init(TDSPOLLWAKEUP *wakeup)
803 {
804 	TDS_SYS_SOCKET sv[2];
805 	int ret;
806 
807 	wakeup->s_signal = wakeup->s_signaled = INVALID_SOCKET;
808 #if defined(__linux__) && HAVE_EVENTFD
809 #  ifdef EFD_CLOEXEC
810 	ret = eventfd(0, EFD_CLOEXEC|EFD_NONBLOCK);
811 #  else
812 	ret = -1;
813 #  endif
814 	/* Linux version up to 2.6.26 do not support flags, try without */
815 	if (ret < 0 && (ret = eventfd(0, 0)) >= 0) {
816 		fcntl(ret, F_SETFD, fcntl(ret, F_GETFD, 0) | FD_CLOEXEC);
817 		fcntl(ret, F_SETFL, fcntl(ret, F_GETFL, 0) | O_NONBLOCK);
818 	}
819 	if (ret >= 0) {
820 		wakeup->s_signaled = ret;
821 		return 0;
822 	}
823 #endif
824 	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
825 	if (ret)
826 		return ret;
827 	wakeup->s_signal   = sv[0];
828 	wakeup->s_signaled = sv[1];
829 	return 0;
830 }
831 
832 void
tds_wakeup_close(TDSPOLLWAKEUP * wakeup)833 tds_wakeup_close(TDSPOLLWAKEUP *wakeup)
834 {
835 	if (!TDS_IS_SOCKET_INVALID(wakeup->s_signal))
836 		CLOSESOCKET(wakeup->s_signal);
837 	if (!TDS_IS_SOCKET_INVALID(wakeup->s_signaled))
838 		CLOSESOCKET(wakeup->s_signaled);
839 }
840 
841 
842 void
tds_wakeup_send(TDSPOLLWAKEUP * wakeup,char cancel)843 tds_wakeup_send(TDSPOLLWAKEUP *wakeup, char cancel)
844 {
845 #if defined(__linux__) && HAVE_EVENTFD
846 	if (wakeup->s_signal == -1) {
847 		uint64_t one = 1;
848 		(void) write(wakeup->s_signaled, &one, sizeof(one));
849 		return;
850 	}
851 #endif
852 	send(wakeup->s_signal, &cancel, sizeof(cancel), 0);
853 }
854 
855 static int
tds_connection_signaled(TDSCONNECTION * conn)856 tds_connection_signaled(TDSCONNECTION *conn)
857 {
858 	int len;
859 	char to_cancel[16];
860 
861 #if defined(__linux__) && HAVE_EVENTFD
862 	if (conn->wakeup.s_signal == -1)
863 		return read(conn->wakeup.s_signaled, to_cancel, 8) > 0;
864 #endif
865 
866 	len = READSOCKET(conn->wakeup.s_signaled, to_cancel, sizeof(to_cancel));
867 	do {
868 		/* no cancel found */
869 		if (len <= 0)
870 			return 0;
871 	} while(!to_cancel[--len]);
872 	return 1;
873 }
874 
875 #if ENABLE_ODBC_MARS
876 static void
tds_check_cancel(TDSCONNECTION * conn)877 tds_check_cancel(TDSCONNECTION *conn)
878 {
879 	TDSSOCKET *tds;
880 	int rc;
881 
882 	if (!tds_connection_signaled(conn))
883 		return;
884 
885 	do {
886 		unsigned n = 0;
887 
888 		rc = TDS_SUCCESS;
889 		tds_mutex_lock(&conn->list_mtx);
890 		/* Here we scan all list searching for sessions that should send cancel packets */
891 		for (; n < conn->num_sessions; ++n)
892 			if (TDSSOCKET_VALID(tds=conn->sessions[n]) && tds->in_cancel == 1) {
893 				/* send cancel */
894 				tds->in_cancel = 2;
895 				tds_mutex_unlock(&conn->list_mtx);
896 				rc = tds_append_cancel(tds);
897 				tds_mutex_lock(&conn->list_mtx);
898 				if (rc != TDS_SUCCESS)
899 					break;
900 			}
901 		tds_mutex_unlock(&conn->list_mtx);
902 		/* for all failed */
903 		/* this must be done outside loop cause it can alter list */
904 		/* this must be done unlocked cause it can lock again */
905 		if (rc != TDS_SUCCESS)
906 			tds_close_socket(tds);
907 	} while(rc != TDS_SUCCESS);
908 }
909 #endif
910 
911 /**
912  * Loops until we have received some characters
913  * return -1 on failure
914  */
915 int
tds_goodread(TDSSOCKET * tds,unsigned char * buf,int buflen)916 tds_goodread(TDSSOCKET * tds, unsigned char *buf, int buflen)
917 {
918 	if (tds == NULL || buf == NULL || buflen < 1)
919 		return -1;
920 
921 	for (;;) {
922 		int len, err;
923 
924 		/* FIXME this block writing from other sessions */
925 		len = tds_select(tds, TDSSELREAD, tds->query_timeout);
926 #if !ENABLE_ODBC_MARS
927 		if (len > 0 && (len & TDSPOLLURG)) {
928 			tds_connection_signaled(tds->conn);
929 			/* send cancel */
930 			if (tds->in_cancel == 1)
931 				tds_put_cancel(tds);
932 			continue;
933 		}
934 #endif
935 		if (len > 0) {
936 			len = tds_socket_read(tds->conn, tds, buf, buflen);
937 			if (len == 0)
938 				continue;
939 			return len;
940 		}
941 
942 		/* error */
943 		if (len < 0) {
944 			if (TDSSOCK_WOULDBLOCK(sock_errno)) /* shouldn't happen, but OK */
945 				continue;
946 			err = sock_errno;
947 			tds_connection_close(tds->conn);
948 			tdserror(tds_get_ctx(tds), tds, TDSEREAD, err);
949 			return -1;
950 		}
951 
952 		/* timeout */
953 		switch (tdserror(tds_get_ctx(tds), tds, TDSETIME, sock_errno)) {
954 		case TDS_INT_CONTINUE:
955 			break;
956 		default:
957 		case TDS_INT_CANCEL:
958 			tds_close_socket(tds);
959 			return -1;
960 		}
961 	}
962 }
963 
964 int
tds_connection_read(TDSSOCKET * tds,unsigned char * buf,int buflen)965 tds_connection_read(TDSSOCKET * tds, unsigned char *buf, int buflen)
966 {
967 	TDSCONNECTION *conn = tds->conn;
968 
969 	if (conn->tls_session)
970 		return tds_ssl_read(conn, buf, buflen);
971 
972 #if ENABLE_ODBC_MARS
973 	return tds_socket_read(conn, tds, buf, buflen);
974 #else
975 	return tds_goodread(tds, buf, buflen);
976 #endif
977 }
978 
979 /**
980  * \param tds the famous socket
981  * \param buffer data to send
982  * \param buflen bytes in buffer
983  * \param last 1 if this is the last packet, else 0
984  * \return length written (>0), <0 on failure
985  */
986 int
tds_goodwrite(TDSSOCKET * tds,const unsigned char * buffer,size_t buflen)987 tds_goodwrite(TDSSOCKET * tds, const unsigned char *buffer, size_t buflen)
988 {
989 	int len;
990 	size_t sent = 0;
991 
992 	assert(tds && buffer);
993 
994 	while (sent < buflen) {
995 		/* TODO if send buffer is full we block receive !!! */
996 		len = tds_select(tds, TDSSELWRITE, tds->query_timeout);
997 
998 		if (len > 0) {
999 			len = tds_socket_write(tds->conn, tds, buffer + sent, buflen - sent);
1000 			if (len == 0)
1001 				continue;
1002 			if (len < 0)
1003 				return len;
1004 
1005 			sent += len;
1006 			continue;
1007 		}
1008 
1009 		/* error */
1010 		if (len < 0) {
1011 			int err = sock_errno;
1012 			char *errstr;
1013 
1014 			if (TDSSOCK_WOULDBLOCK(err)) /* shouldn't happen, but OK, retry */
1015 				continue;
1016 			errstr = sock_strerror(err);
1017 			tdsdump_log(TDS_DBG_NETWORK, "select(2) failed: %d (%s)\n", err, errstr);
1018 			sock_strerror_free(errstr);
1019 			tds_connection_close(tds->conn);
1020 			tdserror(tds_get_ctx(tds), tds, TDSEWRIT, err);
1021 			return -1;
1022 		}
1023 
1024 		/* timeout */
1025 		tdsdump_log(TDS_DBG_NETWORK, "tds_goodwrite(): timed out, asking client\n");
1026 		switch (tdserror(tds_get_ctx(tds), tds, TDSETIME, sock_errno)) {
1027 		case TDS_INT_CONTINUE:
1028 			break;
1029 		default:
1030 		case TDS_INT_CANCEL:
1031 			tds_close_socket(tds);
1032 			return -1;
1033 		}
1034 	}
1035 
1036 	return (int) sent;
1037 }
1038 
1039 void
tds_socket_flush(TDS_SYS_SOCKET sock)1040 tds_socket_flush(TDS_SYS_SOCKET sock)
1041 {
1042 #ifdef USE_CORK
1043 	int opt;
1044 	opt = 0;
1045 	setsockopt(sock, SOL_TCP, TCP_CORK, (const void *) &opt, sizeof(opt));
1046 	opt = 1;
1047 	setsockopt(sock, SOL_TCP, TCP_CORK, (const void *) &opt, sizeof(opt));
1048 #endif
1049 }
1050 
1051 int
tds_connection_write(TDSSOCKET * tds,const unsigned char * buf,int buflen,int final)1052 tds_connection_write(TDSSOCKET *tds, const unsigned char *buf, int buflen, int final)
1053 {
1054 	int sent;
1055 	TDSCONNECTION *conn = tds->conn;
1056 
1057 #if !defined(_WIN32) && !defined(MSG_NOSIGNAL) && !defined(DOS32X) && !defined(SO_NOSIGPIPE)
1058 	void (*oldsig) (int);
1059 
1060 	oldsig = signal(SIGPIPE, SIG_IGN);
1061 	if (oldsig == SIG_ERR) {
1062 		tdsdump_log(TDS_DBG_WARN, "TDS: Warning: Couldn't set SIGPIPE signal to be ignored\n");
1063 	}
1064 #endif
1065 
1066 	if (conn->tls_session)
1067 		sent = tds_ssl_write(conn, buf, buflen);
1068 	else
1069 #if ENABLE_ODBC_MARS
1070 		sent = tds_socket_write(conn, tds, buf, buflen);
1071 #else
1072 		sent = tds_goodwrite(tds, buf, buflen);
1073 #endif
1074 
1075 	/* force packet flush */
1076 	if (final && sent >= buflen)
1077 		tds_socket_flush(tds_get_s(tds));
1078 
1079 #if !defined(_WIN32) && !defined(MSG_NOSIGNAL) && !defined(DOS32X) && !defined(SO_NOSIGPIPE)
1080 	if (signal(SIGPIPE, oldsig) == SIG_ERR) {
1081 		tdsdump_log(TDS_DBG_WARN, "TDS: Warning: Couldn't reset SIGPIPE signal to previous value\n");
1082 	}
1083 #endif
1084 	return sent;
1085 }
1086 
1087 /**
1088  * Get port of all instances
1089  * @return default port number or 0 if error
1090  * @remark experimental, cf. MC-SQLR.pdf.
1091  */
1092 int
tds7_get_instance_ports(FILE * output,struct addrinfo * addr)1093 tds7_get_instance_ports(FILE *output, struct addrinfo *addr)
1094 {
1095 	int num_try;
1096 	struct pollfd fd;
1097 	int retval;
1098 	TDS_SYS_SOCKET s;
1099 	char msg[16*1024];
1100 	int msg_len = 0;
1101 	int port = 0;
1102 	char ipaddr[128];
1103 
1104 
1105 	tds_addrinfo_set_port(addr, 1434);
1106 	tds_addrinfo2str(addr, ipaddr, sizeof(ipaddr));
1107 
1108 	tdsdump_log(TDS_DBG_ERROR, "tds7_get_instance_ports(%s)\n", ipaddr);
1109 
1110 	/* create an UDP socket */
1111 	if (TDS_IS_SOCKET_INVALID(s = socket(addr->ai_family, SOCK_DGRAM, 0))) {
1112 		char *errstr = sock_strerror(sock_errno);
1113 		tdsdump_log(TDS_DBG_ERROR, "socket creation error: %s\n", errstr);
1114 		sock_strerror_free(errstr);
1115 		return 0;
1116 	}
1117 
1118 	/*
1119 	 * on cluster environment is possible that reply packet came from
1120 	 * different IP so do not filter by ip with connect
1121 	 */
1122 
1123 	if (tds_socket_set_nonblocking(s) != 0) {
1124 		CLOSESOCKET(s);
1125 		return 0;
1126 	}
1127 
1128 	/*
1129 	 * Request the instance's port from the server.
1130 	 * There is no easy way to detect if port is closed so we always try to
1131 	 * get a reply from server 16 times.
1132 	 */
1133 	for (num_try = 0; num_try < 16 && msg_len == 0; ++num_try) {
1134 		/* send the request */
1135 		msg[0] = 3;
1136 		if (sendto(s, msg, 1, 0, addr->ai_addr, addr->ai_addrlen) < 0)
1137 			break;
1138 
1139 		fd.fd = s;
1140 		fd.events = POLLIN;
1141 		fd.revents = 0;
1142 
1143 		retval = poll(&fd, 1, 1000);
1144 
1145 		/* on interrupt ignore */
1146 		if (retval < 0 && sock_errno == TDSSOCK_EINTR)
1147 			continue;
1148 
1149 		if (retval == 0) { /* timed out */
1150 #if 1
1151 			tdsdump_log(TDS_DBG_ERROR, "tds7_get_instance_port: timed out on try %d of 16\n", num_try);
1152 			continue;
1153 #else
1154 			int rc;
1155 			tdsdump_log(TDS_DBG_INFO1, "timed out\n");
1156 
1157 			switch(rc = tdserror(NULL, NULL, TDSETIME, 0)) {
1158 			case TDS_INT_CONTINUE:
1159 				continue;	/* try again */
1160 
1161 			default:
1162 				tdsdump_log(TDS_DBG_ERROR, "error: client error handler returned %d\n", rc);
1163 			case TDS_INT_CANCEL:
1164 				CLOSESOCKET(s);
1165 				return 0;
1166 			}
1167 #endif
1168 		}
1169 		if (retval < 0)
1170 			break;
1171 
1172 		/* got data, read and parse */
1173 		if ((msg_len = recv(s, msg, sizeof(msg) - 1, 0)) > 3 && msg[0] == 5) {
1174 			char *name, sep[2] = ";", *save;
1175 
1176 			/* assure null terminated */
1177 			msg[msg_len] = 0;
1178 			tdsdump_dump_buf(TDS_DBG_INFO1, "instance info", msg, msg_len);
1179 
1180 			if (0) {	/* To debug, print the whole string. */
1181 				char *p;
1182 
1183 				for (*sep = '\n', p=msg+3; p < msg + msg_len; p++) {
1184 					if( *p == ';' )
1185 						*p = *sep;
1186 				}
1187 				fputs(msg + 3, output);
1188 			}
1189 
1190 			/*
1191 			 * Parse and print message.
1192 			 */
1193 			name = strtok_r(msg+3, sep, &save);
1194 			while (name && output) {
1195 				int i;
1196 				static const char *const names[] = { "ServerName", "InstanceName", "IsClustered", "Version",
1197 							       "tcp", "np", "via" };
1198 
1199 				for (i=0; name && i < TDS_VECTOR_SIZE(names); i++) {
1200 					const char *value = strtok_r(NULL, sep, &save);
1201 
1202 					if (strcmp(name, names[i]) != 0)
1203 						fprintf(output, "error: expecting '%s', found '%s'\n", names[i], name);
1204 					if (value)
1205 						fprintf(output, "%15s %s\n", name, value);
1206 					else
1207 						break;
1208 
1209 					name = strtok_r(NULL, sep, &save);
1210 
1211 					if (name && strcmp(name, names[0]) == 0)
1212 						break;
1213 				}
1214 				if (name)
1215 					fprintf(output, "\n");
1216 			}
1217 		}
1218 	}
1219 	CLOSESOCKET(s);
1220 	tdsdump_log(TDS_DBG_ERROR, "default instance port is %d\n", port);
1221 	return port;
1222 }
1223 
1224 /**
1225  * Get port of given instance
1226  * @return port number or 0 if error
1227  */
1228 int
tds7_get_instance_port(struct addrinfo * addr,const char * instance)1229 tds7_get_instance_port(struct addrinfo *addr, const char *instance)
1230 {
1231 	int num_try;
1232 	struct pollfd fd;
1233 	int retval;
1234 	TDS_SYS_SOCKET s;
1235 	char msg[1024];
1236 	int msg_len;
1237 	int port = 0;
1238 	char ipaddr[128];
1239 
1240 	tds_addrinfo_set_port(addr, 1434);
1241 	tds_addrinfo2str(addr, ipaddr, sizeof(ipaddr));
1242 
1243 	tdsdump_log(TDS_DBG_ERROR, "tds7_get_instance_port(%s, %s)\n", ipaddr, instance);
1244 
1245 	/* create an UDP socket */
1246 	if (TDS_IS_SOCKET_INVALID(s = socket(addr->ai_family, SOCK_DGRAM, 0))) {
1247 		char *errstr = sock_strerror(sock_errno);
1248 		tdsdump_log(TDS_DBG_ERROR, "socket creation error: %s\n", errstr);
1249 		sock_strerror_free(errstr);
1250 		return 0;
1251 	}
1252 
1253 	/*
1254 	 * on cluster environment is possible that reply packet came from
1255 	 * different IP so do not filter by ip with connect
1256 	 */
1257 
1258 	if (tds_socket_set_nonblocking(s) != 0) {
1259 		CLOSESOCKET(s);
1260 		return 0;
1261 	}
1262 
1263 	/*
1264 	 * Request the instance's port from the server.
1265 	 * There is no easy way to detect if port is closed so we always try to
1266 	 * get a reply from server 16 times.
1267 	 */
1268 	for (num_try = 0; num_try < 16; ++num_try) {
1269 		/* send the request */
1270 		msg[0] = 4;
1271 		strlcpy(msg + 1, instance, sizeof(msg) - 1);
1272 		if (sendto(s, msg, (int)strlen(msg) + 1, 0, addr->ai_addr, addr->ai_addrlen) < 0)
1273 			break;
1274 
1275 		fd.fd = s;
1276 		fd.events = POLLIN;
1277 		fd.revents = 0;
1278 
1279 		retval = poll(&fd, 1, 1000);
1280 
1281 		/* on interrupt ignore */
1282 		if (retval < 0 && sock_errno == TDSSOCK_EINTR)
1283 			continue;
1284 
1285 		if (retval == 0) { /* timed out */
1286 #if 1
1287 			tdsdump_log(TDS_DBG_ERROR, "tds7_get_instance_port: timed out on try %d of 16\n", num_try);
1288 			continue;
1289 #else
1290 			int rc;
1291 			tdsdump_log(TDS_DBG_INFO1, "timed out\n");
1292 
1293 			switch(rc = tdserror(NULL, NULL, TDSETIME, 0)) {
1294 			case TDS_INT_CONTINUE:
1295 				continue;	/* try again */
1296 
1297 			default:
1298 				tdsdump_log(TDS_DBG_ERROR, "error: client error handler returned %d\n", rc);
1299 			case TDS_INT_CANCEL:
1300 				CLOSESOCKET(s);
1301 				return 0;
1302 			}
1303 #endif
1304 		}
1305 		if (retval < 0)
1306 			break;
1307 
1308 		/* TODO pass also connection and set instance/servername ?? */
1309 
1310 		/* got data, read and parse */
1311 		if ((msg_len = recv(s, msg, sizeof(msg) - 1, 0)) > 3 && msg[0] == 5) {
1312 			char *p;
1313 			long l = 0;
1314 			int instance_ok = 0, port_ok = 0;
1315 
1316 			/* assure null terminated */
1317 			msg[msg_len] = 0;
1318 			tdsdump_dump_buf(TDS_DBG_INFO1, "instance info", msg, msg_len);
1319 
1320 			/*
1321 			 * Parse message and check instance name and port.
1322 			 * We don't check servername cause it can be very different from the client's.
1323 			 */
1324 			for (p = msg + 3;;) {
1325 				char *name, *value;
1326 
1327 				name = p;
1328 				p = strchr(p, ';');
1329 				if (!p)
1330 					break;
1331 				*p++ = 0;
1332 
1333 				value = name;
1334 				if (*name) {
1335 					value = p;
1336 					p = strchr(p, ';');
1337 					if (!p)
1338 						break;
1339 					*p++ = 0;
1340 				}
1341 
1342 				if (strcasecmp(name, "InstanceName") == 0) {
1343 					if (strcasecmp(value, instance) != 0)
1344 						break;
1345 					instance_ok = 1;
1346 				} else if (strcasecmp(name, "tcp") == 0) {
1347 					l = strtol(value, &p, 10);
1348 					if (l > 0 && l <= 0xffff && *p == 0)
1349 						port_ok = 1;
1350 				}
1351 			}
1352 			if (port_ok && instance_ok) {
1353 				port = l;
1354 				break;
1355 			}
1356 		}
1357 	}
1358 	CLOSESOCKET(s);
1359 	tdsdump_log(TDS_DBG_ERROR, "instance port is %d\n", port);
1360 	return port;
1361 }
1362 
1363 #if defined(_WIN32)
1364 static const char tds_unknown_wsaerror[] = "undocumented WSA error code";
1365 
1366 char *
tds_prwsaerror(int erc)1367 tds_prwsaerror(int erc)
1368 {
1369 	char *errstr = NULL;
1370 	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, NULL, erc,
1371 		      MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (LPTSTR)&errstr, 0, NULL);
1372 	if (errstr) {
1373 		size_t len = strlen(errstr);
1374 		while (len > 0 && (errstr[len-1] == '\r' || errstr[len-1] == '\n'))
1375 			errstr[len-1] = 0;
1376 		return errstr;
1377 	}
1378 	return (char*) tds_unknown_wsaerror;
1379 }
1380 
1381 void
tds_prwsaerror_free(char * s)1382 tds_prwsaerror_free(char *s)
1383 {
1384 	if (s != tds_unknown_wsaerror)
1385 		LocalFree((HLOCAL) s);
1386 }
1387 #endif
1388 
1389 /** @} */
1390 
1391