Line data Source code
1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 2012 Frediano Ziglio
3 : *
4 : * This library is free software; you can redistribute it and/or
5 : * modify it under the terms of the GNU Library General Public
6 : * License as published by the Free Software Foundation; either
7 : * version 2 of the License, or (at your option) any later version.
8 : *
9 : * This library is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : * Library General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU Library General Public
15 : * License along with this library; if not, write to the
16 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 : * Boston, MA 02111-1307, USA.
18 : */
19 :
20 : #include <config.h>
21 :
22 : #include <stdarg.h>
23 : #include <stdio.h>
24 : #include <assert.h>
25 :
26 : #if HAVE_ERRNO_H
27 : #include <errno.h>
28 : #endif /* HAVE_ERRNO_H */
29 :
30 : #if HAVE_STDLIB_H
31 : #include <stdlib.h>
32 : #endif /* HAVE_STDLIB_H */
33 :
34 : #if HAVE_STRING_H
35 : #include <string.h>
36 : #endif /* HAVE_STRING_H */
37 :
38 : #if HAVE_UNISTD_H
39 : #include <unistd.h>
40 : #endif /* HAVE_UNISTD_H */
41 :
42 : #include <freetds/tds.h>
43 : #include <freetds/bytes.h>
44 : #include <freetds/iconv.h>
45 : #include <freetds/replacements.h>
46 : #include <freetds/checks.h>
47 : #include <freetds/tls.h>
48 :
49 : /**
50 : * \addtogroup network
51 : * @{
52 : */
53 :
54 : #if ENABLE_ODBC_MARS
55 : static TDSRET tds_update_recv_wnd(TDSSOCKET *tds, TDS_UINT new_recv_wnd);
56 : static int tds_packet_write(TDSCONNECTION *conn);
57 : #endif
58 :
59 : /* get packet from the cache */
60 : static TDSPACKET *
61 96670 : tds_get_packet(TDSCONNECTION *conn, unsigned len)
62 : {
63 96670 : TDSPACKET *packet, *to_free = NULL;
64 :
65 96670 : tds_mutex_lock(&conn->list_mtx);
66 196926 : while ((packet = conn->packet_cache) != NULL) {
67 94332 : --conn->num_cached_packets;
68 94332 : conn->packet_cache = packet->next;
69 :
70 : /* return it */
71 94332 : if (packet->capacity >= len) {
72 90746 : TDS_MARK_UNDEFINED(packet->buf, packet->capacity);
73 90746 : packet->next = NULL;
74 90735 : tds_packet_zero_data_start(packet);
75 90746 : packet->data_len = 0;
76 90746 : packet->sid = 0;
77 90746 : break;
78 : }
79 :
80 : /* discard packet if too small */
81 3586 : packet->next = to_free;
82 3586 : to_free = packet;
83 : }
84 96670 : tds_mutex_unlock(&conn->list_mtx);
85 :
86 96670 : if (to_free)
87 3369 : tds_free_packets(to_free);
88 :
89 96670 : if (!packet)
90 5924 : packet = tds_alloc_packet(NULL, len);
91 :
92 96670 : return packet;
93 : }
94 :
95 : /* append packets in cached list. must have the lock! */
96 : static void
97 96753 : tds_packet_cache_add(TDSCONNECTION *conn, TDSPACKET *packet)
98 : {
99 : TDSPACKET *last;
100 96753 : unsigned count = 1;
101 :
102 96753 : assert(conn && packet);
103 96753 : tds_mutex_check_owned(&conn->list_mtx);
104 :
105 96753 : if (conn->num_cached_packets >= 8) {
106 0 : tds_free_packets(packet);
107 0 : return;
108 : }
109 :
110 88 : for (last = packet; last->next; last = last->next)
111 88 : ++count;
112 :
113 96753 : last->next = conn->packet_cache;
114 96753 : conn->packet_cache = packet;
115 96753 : conn->num_cached_packets += count;
116 :
117 : #if ENABLE_EXTRA_CHECKS
118 96753 : count = 0;
119 196874 : for (packet = conn->packet_cache; packet; packet = packet->next)
120 100121 : ++count;
121 96753 : assert(count == conn->num_cached_packets);
122 : #endif
123 : }
124 :
125 : #if ENABLE_ODBC_MARS
126 : /* read partial packet */
127 : static bool
128 119790 : tds_packet_read(TDSCONNECTION *conn, TDSSOCKET *tds)
129 : {
130 119790 : TDSPACKET *packet = conn->recv_packet;
131 : int len;
132 :
133 : /* allocate some space to read data */
134 119790 : if (!packet) {
135 49034 : conn->recv_packet = packet =
136 49034 : tds_get_packet(conn, TDS_MAX(conn->env.block_size + sizeof(TDS72_SMP_HEADER), 512));
137 49034 : if (!packet) goto Memory_Error;
138 49034 : TDS_MARK_UNDEFINED(packet->buf, packet->capacity);
139 49034 : conn->recv_pos = 0;
140 49034 : packet->data_len = 8;
141 : }
142 :
143 119790 : assert(packet->data_start == 0);
144 :
145 119790 : assert(conn->recv_pos < packet->data_len && packet->data_len <= packet->capacity);
146 :
147 119790 : len = tds_connection_read(tds, packet->buf + conn->recv_pos, packet->data_len - conn->recv_pos);
148 119790 : if (len < 0)
149 : goto Severe_Error;
150 119779 : conn->recv_pos += len;
151 119779 : assert(conn->recv_pos <= packet->data_len && packet->data_len <= packet->capacity);
152 :
153 : /* handle SMP */
154 119779 : if (conn->recv_pos > 0 && packet->buf[0] == TDS72_SMP) {
155 : TDS72_SMP_HEADER mars_header;
156 : uint16_t sid;
157 : TDSSOCKET *tds;
158 : TDS_UINT size;
159 :
160 : /* make sure we read the header */
161 29628 : if (conn->recv_pos < sizeof(mars_header)) {
162 9935 : packet->data_len = sizeof(mars_header);
163 39563 : return false;
164 : }
165 :
166 19693 : memcpy(&mars_header, packet->buf, sizeof(mars_header));
167 19693 : tdsdump_dump_buf(TDS_DBG_HEADER, "Received MARS header", &mars_header, sizeof(mars_header));
168 19693 : sid = TDS_GET_A2LE(&mars_header.sid);
169 :
170 : /* FIXME this is done even by caller !! */
171 19693 : tds = NULL;
172 19693 : tds_mutex_lock(&conn->list_mtx);
173 19693 : if (sid < conn->num_sessions) {
174 19693 : tds = conn->sessions[sid];
175 19693 : packet->sid = sid;
176 : }
177 19693 : tds_mutex_unlock(&conn->list_mtx);
178 :
179 19693 : if (tds == BUSY_SOCKET) {
180 5 : if (mars_header.type != TDS_SMP_FIN) {
181 0 : tdsdump_log(TDS_DBG_ERROR, "Received MARS with no session (%u)\n", sid);
182 0 : goto Severe_Error;
183 : }
184 :
185 : /* check if was just a "zombie" socket */
186 5 : tds_mutex_lock(&conn->list_mtx);
187 5 : conn->sessions[sid] = NULL;
188 5 : tds_mutex_unlock(&conn->list_mtx);
189 :
190 : /* reset packet to initial state to reuse it */
191 5 : packet->data_len = 8;
192 5 : conn->recv_pos = 0;
193 5 : return false;
194 : }
195 :
196 19688 : if (!tds) {
197 : /* server sent a unknown packet, close connection */
198 : goto Severe_Error;
199 : }
200 :
201 19688 : tds->send_wnd = TDS_GET_A4LE(&mars_header.wnd);
202 19688 : size = TDS_GET_A4LE(&mars_header.size);
203 19688 : if (mars_header.type == TDS_SMP_ACK) {
204 172 : if (size != sizeof(mars_header))
205 : goto Severe_Error;
206 19516 : } else if (mars_header.type == TDS_SMP_DATA) {
207 19516 : if (size < 0x18 || size > 0xffffu + sizeof(mars_header))
208 : goto Severe_Error;
209 : /* avoid recursive SMP */
210 19516 : if (conn->recv_pos > 16 && packet->buf[16] == TDS72_SMP)
211 : goto Severe_Error;
212 : /* TODO is possible to put 2 TDS packet inside a single DATA ?? */
213 19516 : if (conn->recv_pos >= 20 && TDS_GET_A2BE(&packet->buf[18]) != size - 16)
214 : goto Severe_Error;
215 19516 : tds->recv_seq = TDS_GET_A4LE(&mars_header.seq);
216 : /*
217 : * do not sent ACK here because this would lead to memory waste
218 : * if session is not able to handle all that packets
219 : */
220 0 : } else if (mars_header.type == TDS_SMP_FIN) {
221 0 : if (size != sizeof(mars_header))
222 : goto Severe_Error;
223 : /* this socket shold now not start another session */
224 : // tds_set_state(tds, TDS_DEAD);
225 : } else
226 : goto Severe_Error;
227 :
228 19688 : if (mars_header.type != TDS_SMP_DATA)
229 172 : return conn->recv_pos >= size;
230 19516 : if (packet->data_len < size) {
231 9758 : packet = tds_realloc_packet(packet, size);
232 9758 : if (!packet)
233 : goto Memory_Error;
234 9758 : conn->recv_packet = packet;
235 : }
236 19516 : packet->data_len = size;
237 19516 : if (conn->recv_pos >= size) {
238 9758 : packet->data_start = sizeof(TDS72_SMP_HEADER);
239 9758 : packet->data_len -= sizeof(TDS72_SMP_HEADER);
240 9758 : return true;
241 : }
242 : return false;
243 : }
244 : assert(conn->recv_pos <= packet->data_len && packet->data_len <= packet->capacity);
245 :
246 : /* normal packet */
247 90151 : if (conn->recv_pos >= 8) {
248 83863 : len = TDS_GET_A2BE(&packet->buf[2]);
249 83863 : if (len < 8)
250 : goto Severe_Error;
251 83863 : if (packet->data_len < len) {
252 39092 : packet = tds_realloc_packet(packet, len);
253 39092 : if (!packet) goto Memory_Error;
254 39092 : conn->recv_packet = packet;
255 : }
256 83863 : packet->data_len = len;
257 83863 : return conn->recv_pos >= len;
258 : }
259 : return false;
260 :
261 11 : Memory_Error:
262 11 : Severe_Error:
263 11 : tds_connection_close(conn);
264 11 : tds_free_packets(packet);
265 11 : conn->recv_packet = NULL;
266 11 : return false;
267 : }
268 :
269 : static TDSPACKET*
270 121 : tds_build_packet(TDSSOCKET *tds, unsigned char *buf, unsigned len)
271 : {
272 : unsigned start;
273 : TDS72_SMP_HEADER mars[1], *p;
274 : TDSPACKET *packet;
275 :
276 121 : p = mars;
277 121 : if (buf[0] != TDS72_SMP && tds->conn->mars) {
278 40 : p->signature = TDS72_SMP;
279 40 : p->type = TDS_SMP_DATA;
280 40 : TDS_PUT_A2LE(&p->sid, tds->sid);
281 40 : TDS_PUT_A4LE(&p->size, len+16);
282 40 : ++tds->send_seq;
283 40 : TDS_PUT_A4LE(&p->seq, tds->send_seq);
284 : /* this is the acknowledge we give to server to stop sending !!! */
285 40 : tds->recv_wnd = tds->recv_seq + 4;
286 40 : TDS_PUT_A4LE(&p->wnd, tds->recv_wnd);
287 40 : p++;
288 : }
289 :
290 121 : start = (char*) p - (char *) mars;
291 121 : packet = tds_get_packet(tds->conn, len + start);
292 121 : if (TDS_LIKELY(packet)) {
293 121 : packet->sid = tds->sid;
294 121 : memcpy(packet->buf, mars, start);
295 121 : memcpy(packet->buf + start, buf, len);
296 121 : packet->data_len = len + start;
297 : }
298 121 : return packet;
299 : }
300 :
301 : static void
302 : tds_append_packet(TDSPACKET **p_packet, TDSPACKET *packet)
303 : {
304 96922 : while (*p_packet)
305 372 : p_packet = &((*p_packet)->next);
306 96550 : *p_packet = packet;
307 : }
308 :
309 : int
310 121 : tds_append_cancel(TDSSOCKET *tds)
311 : {
312 : unsigned char buf[8];
313 : TDSPACKET *packet;
314 :
315 121 : buf[0] = TDS_CANCEL;
316 121 : buf[1] = 1;
317 121 : TDS_PUT_A2BE(buf+2, 8);
318 121 : TDS_PUT_A4(buf+4, 0);
319 121 : if (IS_TDS7_PLUS(tds->conn) && !tds->login)
320 90 : buf[6] = 0x01;
321 :
322 121 : packet = tds_build_packet(tds, buf, 8);
323 121 : if (!packet)
324 : return TDS_FAIL;
325 :
326 121 : tds_mutex_lock(&tds->conn->list_mtx);
327 242 : tds_append_packet(&tds->conn->send_packets, packet);
328 121 : tds_mutex_unlock(&tds->conn->list_mtx);
329 :
330 121 : return TDS_SUCCESS;
331 : }
332 :
333 :
334 : static void
335 96745 : tds_connection_network(TDSCONNECTION *conn, TDSSOCKET *tds, int send)
336 : {
337 96745 : assert(!conn->in_net_tds);
338 96745 : conn->in_net_tds = tds;
339 96745 : tds_mutex_unlock(&conn->list_mtx);
340 :
341 : for (;;) {
342 : /* wait packets or update */
343 173013 : int rc = tds_select(tds, conn->send_packets ? TDSSELREAD|TDSSELWRITE : TDSSELREAD, tds->query_timeout);
344 :
345 173013 : if (rc < 0) {
346 : /* FIXME better error report */
347 53 : tds_connection_close(conn);
348 53 : break;
349 : }
350 :
351 : /* change notify */
352 : /* TODO async */
353 :
354 172960 : if (!rc) { /* timeout */
355 153 : tdsdump_log(TDS_DBG_INFO1, "timeout\n");
356 153 : switch (rc = tdserror(tds_get_ctx(tds), tds, TDSETIME, sock_errno)) {
357 128 : case TDS_INT_CONTINUE:
358 128 : continue;
359 25 : default:
360 : case TDS_INT_CANCEL:
361 25 : tds_close_socket(tds);
362 : }
363 25 : break;
364 : }
365 :
366 : /*
367 : * we must write first to catch write errors as
368 : * write errors, not as read
369 : */
370 : /* something to send */
371 172807 : if (conn->send_packets && (rc & POLLOUT) != 0) {
372 : TDSSOCKET *s;
373 :
374 52899 : int sid = tds_packet_write(conn);
375 52899 : if (sid < 0)
376 5245 : continue;
377 :
378 47654 : if (sid == tds->sid)
379 : break; /* return to caller */
380 :
381 10 : tds_mutex_lock(&conn->list_mtx);
382 10 : if (sid < conn->num_sessions) {
383 10 : s = conn->sessions[sid];
384 10 : if (TDSSOCKET_VALID(s))
385 0 : tds_cond_signal(&s->packet_cond);
386 : }
387 10 : tds_mutex_unlock(&conn->list_mtx);
388 : /* avoid using a possible closed connection */
389 10 : continue;
390 : }
391 :
392 : /* received */
393 119908 : if (rc & (POLLIN|POLLHUP)) {
394 : TDSPACKET *packet;
395 : TDSSOCKET *s;
396 :
397 : /* try to read a packet */
398 119790 : if (!tds_packet_read(conn, tds))
399 70767 : continue; /* packet not complete */
400 49023 : packet = conn->recv_packet;
401 49023 : conn->recv_packet = NULL;
402 49023 : conn->recv_pos = 0;
403 :
404 49023 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Received packet", packet->buf, packet->data_start + packet->data_len);
405 :
406 49023 : tds_mutex_lock(&conn->list_mtx);
407 49023 : if (packet->sid < conn->num_sessions) {
408 49023 : s = conn->sessions[packet->sid];
409 49023 : if (TDSSOCKET_VALID(s)) {
410 : /* append to correct session */
411 49023 : if (packet->buf[0] == TDS72_SMP && packet->buf[1] != TDS_SMP_DATA)
412 172 : tds_packet_cache_add(conn, packet);
413 : else
414 48851 : tds_append_packet(&conn->packets, packet);
415 49023 : packet = NULL;
416 : /* notify */
417 49023 : tds_cond_signal(&s->packet_cond);
418 : }
419 : }
420 49023 : tds_mutex_unlock(&conn->list_mtx);
421 49023 : tds_free_packets(packet);
422 : /* if we are receiving return the packet */
423 49023 : if (!send) break;
424 : }
425 : }
426 :
427 96745 : tds_mutex_lock(&conn->list_mtx);
428 96745 : conn->in_net_tds = NULL;
429 96745 : }
430 :
431 : static TDSRET
432 46980 : tds_connection_put_packet(TDSSOCKET *tds, TDSPACKET *packet)
433 : {
434 46980 : TDSCONNECTION *conn = tds->conn;
435 :
436 46980 : CHECK_TDS_EXTRA(tds);
437 :
438 46980 : packet->sid = tds->sid;
439 :
440 46980 : tds_mutex_lock(&conn->list_mtx);
441 46980 : tds->sending_packet = packet;
442 94406 : while (tds->sending_packet) {
443 : int wait_res;
444 :
445 47426 : if (IS_TDSDEAD(tds)) {
446 44 : tdsdump_log(TDS_DBG_NETWORK, "Write attempt when state is TDS_DEAD");
447 : break;
448 : }
449 :
450 : /* limit packet sending looking at sequence/window */
451 47382 : if (packet && (int32_t) (tds->send_seq - tds->send_wnd) < 0) {
452 : /* prepare MARS header if needed */
453 46976 : if (tds->conn->mars) {
454 : TDS72_SMP_HEADER *hdr;
455 :
456 : /* fill SMP data */
457 9432 : hdr = (TDS72_SMP_HEADER *) packet->buf;
458 9432 : hdr->signature = TDS72_SMP;
459 9432 : hdr->type = TDS_SMP_DATA;
460 9432 : TDS_PUT_A2LE(&hdr->sid, packet->sid);
461 9432 : TDS_PUT_A4LE(&hdr->size, packet->data_start + packet->data_len);
462 9432 : ++tds->send_seq;
463 9432 : TDS_PUT_A4LE(&hdr->seq, tds->send_seq);
464 : /* this is the acknowledge we give to server to stop sending */
465 9432 : tds->recv_wnd = tds->recv_seq + 4;
466 9432 : TDS_PUT_A4LE(&hdr->wnd, tds->recv_wnd);
467 : }
468 :
469 : /* append packet */
470 93952 : tds_append_packet(&conn->send_packets, packet);
471 46976 : packet = NULL;
472 : }
473 :
474 : /* network ok ? process network */
475 47382 : if (!conn->in_net_tds) {
476 47382 : tds_connection_network(conn, tds, packet ? 0 : 1);
477 47382 : if (tds->sending_packet)
478 446 : continue;
479 : /* here we are sure we sent the packet */
480 : break;
481 : }
482 :
483 : /* signal thread processing network to handle our packet */
484 : /* TODO check result */
485 0 : tds_wakeup_send(&conn->wakeup, 0);
486 :
487 : /* wait local condition */
488 0 : wait_res = tds_cond_timedwait(&tds->packet_cond, &conn->list_mtx, tds->query_timeout);
489 0 : if (wait_res != ETIMEDOUT)
490 0 : continue;
491 :
492 0 : tds_mutex_unlock(&conn->list_mtx);
493 0 : if (tdserror(tds_get_ctx(tds), tds, TDSETIME, ETIMEDOUT) != TDS_INT_CONTINUE) {
494 0 : tds->sending_packet = NULL;
495 0 : tds_close_socket(tds);
496 0 : tds_free_packets(packet);
497 0 : return TDS_FAIL;
498 : }
499 0 : tds_mutex_lock(&conn->list_mtx);
500 : }
501 46980 : tds->sending_packet = NULL;
502 46980 : tds_mutex_unlock(&conn->list_mtx);
503 46980 : if (TDS_UNLIKELY(packet)) {
504 4 : tds_free_packets(packet);
505 4 : return TDS_FAIL;
506 : }
507 46976 : if (IS_TDSDEAD(tds))
508 : return TDS_FAIL;
509 46936 : return TDS_SUCCESS;
510 : }
511 : #endif /* ENABLE_ODBC_MARS */
512 :
513 : /**
514 : * Read in one 'packet' from the server. This is a wrapped outer packet of
515 : * the protocol (they bundle result packets into chunks and wrap them at
516 : * what appears to be 512 bytes regardless of how that breaks internal packet
517 : * up. (tetherow\@nol.org)
518 : * @return bytes read or -1 on failure
519 : */
520 : int
521 97805 : tds_read_packet(TDSSOCKET * tds)
522 : {
523 : #if ENABLE_ODBC_MARS
524 48889 : TDSCONNECTION *conn = tds->conn;
525 :
526 48889 : tds_mutex_lock(&conn->list_mtx);
527 :
528 : for (;;) {
529 : int wait_res;
530 : TDSPACKET **p_packet;
531 :
532 98252 : if (IS_TDSDEAD(tds)) {
533 38 : tdsdump_log(TDS_DBG_NETWORK, "Read attempt when state is TDS_DEAD\n");
534 : break;
535 : }
536 :
537 : /* if there is a packet for me return it */
538 98366 : for (p_packet = &conn->packets; *p_packet; p_packet = &(*p_packet)->next)
539 49003 : if ((*p_packet)->sid == tds->sid)
540 : break;
541 :
542 98214 : if (*p_packet) {
543 : /* remove our packet from list */
544 48851 : TDSPACKET *packet = *p_packet;
545 48851 : *p_packet = packet->next;
546 48851 : tds_packet_cache_add(conn, tds->recv_packet);
547 48851 : tds_mutex_unlock(&conn->list_mtx);
548 :
549 48851 : packet->next = NULL;
550 48851 : tds->recv_packet = packet;
551 :
552 48851 : tds->in_buf = packet->buf + packet->data_start;
553 48851 : tds->in_len = packet->data_len;
554 48851 : tds->in_pos = 8;
555 48851 : tds->in_flag = tds->in_buf[0];
556 :
557 : /* send acknowledge if needed */
558 48851 : if ((int32_t) (tds->recv_seq + 2 - tds->recv_wnd) >= 0)
559 371 : tds_update_recv_wnd(tds, tds->recv_seq + 4);
560 :
561 48851 : return tds->in_len;
562 : }
563 :
564 : /* network ok ? process network */
565 49363 : if (!conn->in_net_tds) {
566 49363 : tds_connection_network(conn, tds, 0);
567 49363 : continue;
568 : }
569 :
570 : /* wait local condition */
571 0 : wait_res = tds_cond_timedwait(&tds->packet_cond, &conn->list_mtx, tds->query_timeout);
572 0 : if (wait_res != ETIMEDOUT)
573 0 : continue;
574 :
575 0 : tds_mutex_unlock(&conn->list_mtx);
576 0 : if (tdserror(tds_get_ctx(tds), tds, TDSETIME, ETIMEDOUT) != TDS_INT_CONTINUE) {
577 0 : tds_close_socket(tds);
578 0 : return -1;
579 : }
580 0 : tds_mutex_lock(&conn->list_mtx);
581 : }
582 :
583 38 : tds_mutex_unlock(&conn->list_mtx);
584 38 : return -1;
585 : #else /* !ENABLE_ODBC_MARS */
586 48916 : unsigned char *pkt = tds->in_buf, *p, *end;
587 :
588 48916 : if (IS_TDSDEAD(tds)) {
589 0 : tdsdump_log(TDS_DBG_NETWORK, "Read attempt when state is TDS_DEAD");
590 : return -1;
591 : }
592 :
593 48916 : tds->in_len = 0;
594 48916 : tds->in_pos = 0;
595 201259 : for (p = pkt, end = p+8; p < end;) {
596 103465 : ptrdiff_t len = tds_connection_read(tds, p, end - p);
597 103465 : if (len <= 0) {
598 38 : tds_close_socket(tds);
599 38 : return -1;
600 : }
601 :
602 103427 : p += len;
603 103427 : if (p - pkt >= 4) {
604 103427 : unsigned pktlen = TDS_GET_A2BE(pkt+2);
605 : /* packet must at least contains header */
606 103427 : if (TDS_UNLIKELY(pktlen < 8)) {
607 0 : tds_close_socket(tds);
608 0 : return -1;
609 : }
610 103427 : if (TDS_UNLIKELY(pktlen > tds->recv_packet->capacity)) {
611 1325 : TDSPACKET *packet = tds_realloc_packet(tds->recv_packet, pktlen);
612 1325 : if (TDS_UNLIKELY(!packet)) {
613 0 : tds_close_socket(tds);
614 0 : return -1;
615 : }
616 1325 : tds->recv_packet = packet;
617 1325 : pkt = packet->buf;
618 1325 : p = pkt + (p-tds->in_buf);
619 1325 : tds->in_buf = pkt;
620 : }
621 103427 : end = pkt + pktlen;
622 : }
623 : }
624 :
625 : /* set the received packet type flag */
626 48878 : tds->in_flag = pkt[0];
627 :
628 : /* Set the length and pos (not sure what pos is used for now */
629 48878 : tds->in_len = (unsigned int) (p - pkt);
630 48878 : tds->in_pos = 8;
631 48878 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Received packet", tds->in_buf, tds->in_len);
632 :
633 48878 : return tds->in_len;
634 : #endif /* !ENABLE_ODBC_MARS */
635 : }
636 :
637 : #if ENABLE_ODBC_MARS
638 : static TDSRET
639 371 : tds_update_recv_wnd(TDSSOCKET *tds, TDS_UINT new_recv_wnd)
640 : {
641 : TDS72_SMP_HEADER *mars;
642 : TDSPACKET *packet;
643 :
644 371 : if (!tds->conn->mars)
645 : return TDS_SUCCESS;
646 :
647 371 : packet = tds_get_packet(tds->conn, sizeof(*mars));
648 371 : if (!packet)
649 : return TDS_FAIL; /* TODO check result */
650 :
651 371 : packet->data_len = sizeof(*mars);
652 371 : packet->sid = tds->sid;
653 :
654 371 : mars = (TDS72_SMP_HEADER *) packet->buf;
655 371 : mars->signature = TDS72_SMP;
656 371 : mars->type = TDS_SMP_ACK;
657 371 : TDS_PUT_A2LE(&mars->sid, tds->sid);
658 371 : mars->size = TDS_HOST4LE(16);
659 371 : TDS_PUT_A4LE(&mars->seq, tds->send_seq);
660 371 : tds->recv_wnd = new_recv_wnd;
661 371 : TDS_PUT_A4LE(&mars->wnd, tds->recv_wnd);
662 :
663 371 : tds_mutex_lock(&tds->conn->list_mtx);
664 742 : tds_append_packet(&tds->conn->send_packets, packet);
665 371 : tds_mutex_unlock(&tds->conn->list_mtx);
666 :
667 371 : return TDS_SUCCESS;
668 : }
669 :
670 : static TDSRET
671 231 : tds_append_fin_syn(TDSSOCKET *tds, uint8_t type)
672 : {
673 : TDS72_SMP_HEADER mars;
674 : TDSPACKET *packet;
675 :
676 231 : if (!tds->conn->mars)
677 : return TDS_SUCCESS;
678 :
679 231 : mars.signature = TDS72_SMP;
680 231 : mars.type = type;
681 231 : TDS_PUT_A2LE(&mars.sid, tds->sid);
682 231 : mars.size = TDS_HOST4LE(16);
683 231 : TDS_PUT_A4LE(&mars.seq, tds->send_seq);
684 231 : tds->recv_wnd = tds->recv_seq + 4;
685 231 : TDS_PUT_A4LE(&mars.wnd, tds->recv_wnd);
686 :
687 : /* do not use tds_get_packet as it require no lock ! */
688 231 : packet = tds_alloc_packet(&mars, sizeof(mars));
689 231 : if (!packet)
690 : return TDS_FAIL; /* TODO check result */
691 231 : packet->sid = tds->sid;
692 :
693 : /* we already hold lock so do not lock */
694 462 : tds_append_packet(&tds->conn->send_packets, packet);
695 :
696 231 : if (type == TDS_SMP_FIN) {
697 : /* now is no more an active session */
698 10 : tds->conn->sessions[tds->sid] = BUSY_SOCKET;
699 10 : tds_set_state(tds, TDS_DEAD);
700 : }
701 :
702 : return TDS_SUCCESS;
703 : }
704 :
705 : /**
706 : * Append a SMP FIN packet.
707 : * tds->conn->list_mtx must be locked.
708 : */
709 : TDSRET
710 10 : tds_append_fin(TDSSOCKET *tds)
711 : {
712 10 : return tds_append_fin_syn(tds, TDS_SMP_FIN);
713 : }
714 :
715 : /**
716 : * Append a SMP SYN packet.
717 : * tds->conn->list_mtx must be unlocked.
718 : */
719 : TDSRET
720 221 : tds_append_syn(TDSSOCKET *tds)
721 : {
722 : TDSRET ret;
723 221 : tds_mutex_lock(&tds->conn->list_mtx);
724 221 : ret = tds_append_fin_syn(tds, TDS_SMP_SYN);
725 221 : tds_mutex_unlock(&tds->conn->list_mtx);
726 221 : return ret;
727 : }
728 : #endif /* ENABLE_ODBC_MARS */
729 :
730 :
731 : TDS_COMPILE_CHECK(additional, TDS_ADDITIONAL_SPACE != 0);
732 :
733 : TDSRET
734 93310 : tds_write_packet(TDSSOCKET * tds, unsigned char final)
735 : {
736 : TDSRET res;
737 93310 : unsigned int left = 0;
738 93310 : TDSPACKET *pkt = tds->send_packet, *pkt_next = NULL;
739 :
740 93310 : CHECK_TDS_EXTRA(tds);
741 :
742 : #if !ENABLE_ODBC_MARS
743 46284 : if (tds->frozen)
744 : #endif
745 : {
746 47144 : pkt->next = pkt_next = tds_get_packet(tds->conn, pkt->capacity);
747 47144 : if (!pkt_next)
748 : return TDS_FAIL;
749 :
750 : #if ENABLE_ODBC_MARS
751 47026 : if (tds->conn->mars)
752 9456 : pkt_next->data_start = sizeof(TDS72_SMP_HEADER);
753 : #endif
754 : }
755 :
756 93310 : if (tds->out_pos > tds->out_buf_max) {
757 506 : left = tds->out_pos - tds->out_buf_max;
758 248 : if (pkt_next)
759 268 : memcpy(pkt_next->buf + tds_packet_get_data_start(pkt_next) + 8, tds->out_buf + tds->out_buf_max, left);
760 506 : tds->out_pos = tds->out_buf_max;
761 : }
762 :
763 : /* we must assure server can accept our packet looking at
764 : * send_wnd and waiting for proper send_wnd if send_seq > send_wnd
765 : */
766 93310 : tds->out_buf[0] = tds->out_flag;
767 93310 : tds->out_buf[1] = final;
768 93310 : TDS_PUT_A2BE(tds->out_buf+2, tds->out_pos);
769 93310 : TDS_PUT_A2BE(tds->out_buf+4, tds->conn->client_spid);
770 93310 : TDS_PUT_A2(tds->out_buf+6, 0);
771 93310 : if (IS_TDS7_PLUS(tds->conn) && !tds->login)
772 65102 : tds->out_buf[6] = 0x01;
773 :
774 93310 : if (tds->frozen) {
775 336 : pkt->data_len = tds->out_pos;
776 336 : tds_set_current_send_packet(tds, pkt_next);
777 336 : tds->out_pos = left + 8;
778 336 : CHECK_TDS_EXTRA(tds);
779 336 : return TDS_SUCCESS;
780 : }
781 :
782 : #if ENABLE_ODBC_MARS
783 46808 : pkt->data_len = tds->out_pos;
784 46808 : pkt->next = NULL;
785 46808 : tds_set_current_send_packet(tds, pkt_next);
786 46808 : res = tds_connection_put_packet(tds, pkt);
787 : #else /* !ENABLE_ODBC_MARS */
788 46166 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Sending packet", tds->out_buf, tds->out_pos);
789 :
790 : /* GW added in check for write() returning <0 and SIGPIPE checking */
791 92332 : res = tds_connection_write(tds, tds->out_buf, tds->out_pos, final) <= 0 ?
792 46166 : TDS_FAIL : TDS_SUCCESS;
793 :
794 46166 : memcpy(tds->out_buf + 8, tds->out_buf + tds->out_buf_max, left);
795 : #endif /* !ENABLE_ODBC_MARS */
796 :
797 92974 : tds->out_pos = left + 8;
798 :
799 92974 : if (TDS_UNLIKELY(tds->conn->encrypt_single_packet)) {
800 732 : tds->conn->encrypt_single_packet = 0;
801 732 : tds_ssl_deinit(tds->conn);
802 : }
803 :
804 : return res;
805 : }
806 :
807 : #if !ENABLE_ODBC_MARS
808 : int
809 563 : tds_put_cancel(TDSSOCKET * tds)
810 : {
811 : unsigned char out_buf[8];
812 : ptrdiff_t sent;
813 :
814 563 : out_buf[0] = TDS_CANCEL; /* out_flag */
815 563 : out_buf[1] = 1; /* final */
816 563 : out_buf[2] = 0;
817 563 : out_buf[3] = 8;
818 563 : TDS_PUT_A4(out_buf+4, 0);
819 563 : if (IS_TDS7_PLUS(tds->conn) && !tds->login)
820 476 : out_buf[6] = 0x01;
821 :
822 563 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Sending packet", out_buf, 8);
823 :
824 563 : sent = tds_connection_write(tds, out_buf, 8, 1);
825 :
826 563 : if (sent > 0)
827 557 : tds->in_cancel = 2;
828 :
829 : /* GW added in check for write() returning <0 and SIGPIPE checking */
830 563 : return sent <= 0 ? TDS_FAIL : TDS_SUCCESS;
831 : }
832 : #endif /* !ENABLE_ODBC_MARS */
833 :
834 :
835 : #if ENABLE_ODBC_MARS
836 : static int
837 52899 : tds_packet_write(TDSCONNECTION *conn)
838 : {
839 : int sent;
840 : int final;
841 52899 : TDSPACKET *packet = conn->send_packets;
842 :
843 52899 : assert(packet);
844 :
845 52899 : if (conn->send_pos == 0)
846 47694 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Sending packet", packet->buf, packet->data_start + packet->data_len);
847 :
848 : /* take into account other session packets */
849 52899 : if (packet->next != NULL)
850 : final = 0;
851 : /* take into account other packets for this session */
852 52609 : else if (packet->buf[0] != TDS72_SMP)
853 42805 : final = packet->buf[1] & 1;
854 : else
855 : final = 1;
856 :
857 52899 : sent = tds_connection_write(conn->in_net_tds, packet->buf + conn->send_pos,
858 52899 : packet->data_start + packet->data_len - conn->send_pos, final);
859 :
860 52899 : if (TDS_UNLIKELY(sent < 0)) {
861 : /* TODO tdserror called ?? */
862 40 : tds_connection_close(conn);
863 40 : return -1;
864 : }
865 :
866 : /* update sent data */
867 52859 : conn->send_pos += sent;
868 : /* remove packet if sent all data */
869 52859 : if (conn->send_pos >= packet->data_start + packet->data_len) {
870 47654 : uint16_t sid = packet->sid;
871 : TDSSOCKET *tds;
872 47654 : tds_mutex_lock(&conn->list_mtx);
873 47654 : tds = conn->sessions[sid];
874 47654 : if (TDSSOCKET_VALID(tds) && tds->sending_packet == packet)
875 46936 : tds->sending_packet = NULL;
876 47654 : conn->send_packets = packet->next;
877 47654 : packet->next = NULL;
878 47654 : tds_packet_cache_add(conn, packet);
879 47654 : tds_mutex_unlock(&conn->list_mtx);
880 47654 : conn->send_pos = 0;
881 47654 : return sid;
882 : }
883 :
884 : return -1;
885 : }
886 : #endif /* ENABLE_ODBC_MARS */
887 :
888 : /**
889 : * Stop writing to server and cache every packet not sending them to server.
890 : * This is used to write data without worrying to compute length before.
891 : * If size_len is provided the number of bytes written between ::tds_freeze and
892 : * ::tds_freeze_close will be written as a number of size size_len.
893 : * This call should be followed by a ::tds_freeze_close, ::tds_freeze_close_len or
894 : * a ::tds_freeze_abort. Failing to match ::tds_freeze with a close would possibly
895 : * result in a disconnection from the server.
896 : *
897 : * @param[out] freeze structure to initialize
898 : * @param size_len length of the size to automatically write on close (0, 1, 2, or 4)
899 : */
900 : void
901 79348 : tds_freeze(TDSSOCKET *tds, TDSFREEZE *freeze, unsigned size_len)
902 : {
903 79348 : CHECK_TDS_EXTRA(tds);
904 79348 : tds_extra_assert(size_len <= 4 && size_len != 3);
905 :
906 79348 : if (tds->out_pos > tds->out_buf_max)
907 15 : tds_write_packet(tds, 0x0);
908 :
909 79348 : if (!tds->frozen)
910 54705 : tds->frozen_packets = tds->send_packet;
911 :
912 79348 : ++tds->frozen;
913 79348 : freeze->tds = tds;
914 79348 : freeze->pkt = tds->send_packet;
915 79348 : freeze->pkt_pos = tds->out_pos;
916 79348 : freeze->size_len = size_len;
917 79348 : if (size_len)
918 73600 : tds_put_n(tds, NULL, size_len);
919 :
920 79348 : CHECK_FREEZE_EXTRA(freeze);
921 79348 : }
922 :
923 : /**
924 : * Compute how many bytes has been written from freeze
925 : *
926 : * @return bytes written since ::tds_freeze call
927 : */
928 : unsigned int
929 69648 : tds_freeze_written(TDSFREEZE *freeze)
930 : {
931 69648 : TDSSOCKET *tds = freeze->tds;
932 69648 : TDSPACKET *pkt = freeze->pkt;
933 : unsigned int size;
934 :
935 69648 : CHECK_FREEZE_EXTRA(freeze);
936 :
937 : /* last packet needs special handling */
938 69648 : size = tds->out_pos;
939 :
940 : /* packets before last */
941 70032 : for (; pkt->next != NULL; pkt = pkt->next)
942 384 : size += pkt->data_len - 8;
943 :
944 69648 : return size - freeze->pkt_pos;
945 : }
946 :
947 : /**
948 : * Discard all data written after the freeze
949 : *
950 : * After this call freeze should not be used.
951 : *
952 : * @param[in] freeze structure to work on
953 : */
954 : TDSRET
955 30 : tds_freeze_abort(TDSFREEZE *freeze)
956 : {
957 30 : TDSSOCKET *tds = freeze->tds;
958 30 : TDSPACKET *pkt = freeze->pkt;
959 :
960 30 : CHECK_FREEZE_EXTRA(freeze);
961 :
962 30 : if (pkt->next) {
963 15 : tds_mutex_lock(&tds->conn->list_mtx);
964 15 : tds_packet_cache_add(tds->conn, pkt->next);
965 15 : tds_mutex_unlock(&tds->conn->list_mtx);
966 15 : pkt->next = NULL;
967 :
968 : tds_set_current_send_packet(tds, pkt);
969 : }
970 30 : tds->out_pos = freeze->pkt_pos;
971 30 : pkt->data_len = 8;
972 :
973 30 : --tds->frozen;
974 30 : if (!tds->frozen)
975 30 : tds->frozen_packets = NULL;
976 30 : freeze->tds = NULL;
977 30 : return TDS_SUCCESS;
978 : }
979 :
980 : /**
981 : * Stop keeping data for this specific freeze.
982 : *
983 : * If size_len was used for ::tds_freeze this function write the written bytes
984 : * at position when ::tds_freeze was called.
985 : * After this call freeze should not be used.
986 : *
987 : * @param[in] freeze structure to work on
988 : */
989 : TDSRET
990 23866 : tds_freeze_close(TDSFREEZE *freeze)
991 : {
992 23866 : return tds_freeze_close_len(freeze, freeze->size_len ? tds_freeze_written(freeze) - freeze->size_len : 0);
993 : }
994 :
995 : /**
996 : * Stop keeping data for this specific freeze.
997 : *
998 : * If size_len was used for ::tds_freeze this function write the written bytes
999 : * at position when ::tds_freeze was called.
1000 : * After this call freeze should not be used.
1001 : * Similar to ::tds_freeze_close but count is written in unit, not bytes.
1002 : *
1003 : * @param[in] freeze structure to work on
1004 : */
1005 : TDSRET
1006 14094 : tds_freeze_close_string(TDSFREEZE *freeze)
1007 : {
1008 14094 : size_t written = tds_freeze_written(freeze) - freeze->size_len;
1009 14094 : if (IS_TDS7_PLUS(freeze->tds->conn))
1010 14094 : written /= 2;
1011 14094 : return tds_freeze_close_len(freeze, written);
1012 : }
1013 :
1014 : static void
1015 : tds_freeze_update_size(const TDSFREEZE *freeze, int32_t size)
1016 : {
1017 : TDSPACKET *pkt;
1018 73570 : unsigned pos = freeze->pkt_pos;
1019 73570 : unsigned size_len = freeze->size_len;
1020 :
1021 73570 : pkt = freeze->pkt;
1022 : do {
1023 235424 : if (pos >= pkt->data_len && pkt->next) {
1024 15 : pkt = pkt->next;
1025 15 : pos = 8;
1026 : }
1027 235424 : pkt->buf[tds_packet_get_data_start(pkt) + pos] = size & 0xffu;
1028 235424 : size >>= 8;
1029 235424 : pos++;
1030 235424 : } while (--size_len);
1031 : }
1032 :
1033 : /**
1034 : * Stop keeping data for this specific freeze.
1035 : *
1036 : * Similar to ::tds_freeze_close but specify the size to be written instead
1037 : * of letting ::tds_freeze_close compute it.
1038 : * After this call freeze should not be used.
1039 : *
1040 : * @param[in] freeze structure to work on
1041 : * @param[in] size size to write
1042 : */
1043 : TDSRET
1044 79318 : tds_freeze_close_len(TDSFREEZE *freeze, int32_t size)
1045 : {
1046 79318 : TDSSOCKET *tds = freeze->tds;
1047 : TDSPACKET *pkt;
1048 : #if !ENABLE_ODBC_MARS
1049 39545 : TDSPACKET *last_pkt_sent = NULL;
1050 : #endif
1051 :
1052 79318 : CHECK_FREEZE_EXTRA(freeze);
1053 :
1054 79318 : if (freeze->size_len)
1055 73570 : tds_freeze_update_size(freeze, size);
1056 :
1057 : /* if not last freeze we need just to update size */
1058 79318 : freeze->tds = NULL;
1059 79318 : if (--tds->frozen != 0)
1060 : return TDS_SUCCESS;
1061 :
1062 54675 : tds->frozen_packets = NULL;
1063 54675 : pkt = freeze->pkt;
1064 109587 : while (pkt->next) {
1065 264 : TDSPACKET *next = pkt->next;
1066 : TDSRET rc;
1067 : #if ENABLE_ODBC_MARS
1068 172 : pkt->next = NULL;
1069 172 : freeze->pkt = next;
1070 : /* packet will get owned by function, no need to release it */
1071 172 : rc = tds_connection_put_packet(tds, pkt);
1072 : #else
1073 184 : rc = tds_connection_write(tds, pkt->buf, pkt->data_len, 0) <= 0 ?
1074 92 : TDS_FAIL : TDS_SUCCESS;
1075 92 : last_pkt_sent = pkt;
1076 : #endif
1077 264 : if (TDS_UNLIKELY(TDS_FAILED(rc))) {
1078 54 : while (next->next) {
1079 : pkt = next;
1080 : next = pkt->next;
1081 : }
1082 27 : tds_extra_assert(pkt->next != NULL);
1083 27 : tds_extra_assert(pkt->next == tds->send_packet);
1084 :
1085 27 : pkt->next = NULL;
1086 27 : tds_mutex_lock(&tds->conn->list_mtx);
1087 27 : tds_packet_cache_add(tds->conn, freeze->pkt);
1088 27 : tds_mutex_unlock(&tds->conn->list_mtx);
1089 27 : return rc;
1090 : }
1091 : pkt = next;
1092 : }
1093 :
1094 54648 : tds_extra_assert(pkt->next == NULL);
1095 54648 : tds_extra_assert(pkt == tds->send_packet);
1096 :
1097 : #if !ENABLE_ODBC_MARS
1098 27231 : if (last_pkt_sent) {
1099 34 : tds_extra_assert(last_pkt_sent->next == pkt);
1100 34 : last_pkt_sent->next = NULL;
1101 34 : tds_mutex_lock(&tds->conn->list_mtx);
1102 34 : tds_packet_cache_add(tds->conn, freeze->pkt);
1103 34 : tds_mutex_unlock(&tds->conn->list_mtx);
1104 : }
1105 : #endif
1106 :
1107 : /* keep final packet so we can continue to add data */
1108 27417 : return TDS_SUCCESS;
1109 : }
1110 :
1111 : /** @} */
|