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 96606 : tds_get_packet(TDSCONNECTION *conn, unsigned len)
62 : {
63 96606 : TDSPACKET *packet, *to_free = NULL;
64 :
65 96606 : tds_mutex_lock(&conn->list_mtx);
66 196784 : while ((packet = conn->packet_cache) != NULL) {
67 94275 : --conn->num_cached_packets;
68 94275 : conn->packet_cache = packet->next;
69 :
70 : /* return it */
71 94275 : if (packet->capacity >= len) {
72 90703 : TDS_MARK_UNDEFINED(packet->buf, packet->capacity);
73 90703 : packet->next = NULL;
74 90693 : tds_packet_zero_data_start(packet);
75 90703 : packet->data_len = 0;
76 90703 : packet->sid = 0;
77 90703 : break;
78 : }
79 :
80 : /* discard packet if too small */
81 3572 : packet->next = to_free;
82 3572 : to_free = packet;
83 : }
84 96606 : tds_mutex_unlock(&conn->list_mtx);
85 :
86 96606 : if (to_free)
87 3357 : tds_free_packets(to_free);
88 :
89 96606 : if (!packet)
90 5903 : packet = tds_alloc_packet(NULL, len);
91 :
92 96606 : return packet;
93 : }
94 :
95 : /* append packets in cached list. must have the lock! */
96 : static void
97 96689 : tds_packet_cache_add(TDSCONNECTION *conn, TDSPACKET *packet)
98 : {
99 : TDSPACKET *last;
100 96689 : unsigned count = 1;
101 :
102 96689 : assert(conn && packet);
103 96689 : tds_mutex_check_owned(&conn->list_mtx);
104 :
105 96689 : 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 96689 : last->next = conn->packet_cache;
114 96689 : conn->packet_cache = packet;
115 96689 : conn->num_cached_packets += count;
116 :
117 : #if ENABLE_EXTRA_CHECKS
118 96689 : count = 0;
119 196499 : for (packet = conn->packet_cache; packet; packet = packet->next)
120 99810 : ++count;
121 96689 : assert(count == conn->num_cached_packets);
122 : #endif
123 : }
124 :
125 : #if ENABLE_ODBC_MARS
126 : /* read partial packet */
127 : static bool
128 119702 : tds_packet_read(TDSCONNECTION *conn, TDSSOCKET *tds)
129 : {
130 119702 : TDSPACKET *packet = conn->recv_packet;
131 : int len;
132 :
133 : /* allocate some space to read data */
134 119702 : if (!packet) {
135 49003 : conn->recv_packet = packet =
136 49003 : tds_get_packet(conn, TDS_MAX(conn->env.block_size + sizeof(TDS72_SMP_HEADER), 512));
137 49003 : if (!packet) goto Memory_Error;
138 49003 : TDS_MARK_UNDEFINED(packet->buf, packet->capacity);
139 49003 : conn->recv_pos = 0;
140 49003 : packet->data_len = 8;
141 : }
142 :
143 119702 : assert(packet->data_start == 0);
144 :
145 119702 : assert(conn->recv_pos < packet->data_len && packet->data_len <= packet->capacity);
146 :
147 119702 : len = tds_connection_read(tds, packet->buf + conn->recv_pos, packet->data_len - conn->recv_pos);
148 119702 : if (len < 0)
149 : goto Severe_Error;
150 119691 : conn->recv_pos += len;
151 119691 : assert(conn->recv_pos <= packet->data_len && packet->data_len <= packet->capacity);
152 :
153 : /* handle SMP */
154 119691 : 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 29472 : if (conn->recv_pos < sizeof(mars_header)) {
162 9883 : packet->data_len = sizeof(mars_header);
163 39355 : return false;
164 : }
165 :
166 19589 : memcpy(&mars_header, packet->buf, sizeof(mars_header));
167 19589 : tdsdump_dump_buf(TDS_DBG_HEADER, "Received MARS header", &mars_header, sizeof(mars_header));
168 19589 : sid = TDS_GET_A2LE(&mars_header.sid);
169 :
170 : /* FIXME this is done even by caller !! */
171 19589 : tds = NULL;
172 19589 : tds_mutex_lock(&conn->list_mtx);
173 19589 : if (sid < conn->num_sessions) {
174 19589 : tds = conn->sessions[sid];
175 19589 : packet->sid = sid;
176 : }
177 19589 : tds_mutex_unlock(&conn->list_mtx);
178 :
179 19589 : 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 19584 : if (!tds) {
197 : /* server sent a unknown packet, close connection */
198 : goto Severe_Error;
199 : }
200 :
201 19584 : tds->send_wnd = TDS_GET_A4LE(&mars_header.wnd);
202 19584 : size = TDS_GET_A4LE(&mars_header.size);
203 19584 : if (mars_header.type == TDS_SMP_ACK) {
204 172 : if (size != sizeof(mars_header))
205 : goto Severe_Error;
206 19412 : } else if (mars_header.type == TDS_SMP_DATA) {
207 19412 : if (size < 0x18 || size > 0xffffu + sizeof(mars_header))
208 : goto Severe_Error;
209 : /* avoid recursive SMP */
210 19412 : 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 19412 : if (conn->recv_pos >= 20 && TDS_GET_A2BE(&packet->buf[18]) != size - 16)
214 : goto Severe_Error;
215 19412 : 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 19584 : if (mars_header.type != TDS_SMP_DATA)
229 172 : return conn->recv_pos >= size;
230 19412 : if (packet->data_len < size) {
231 9706 : packet = tds_realloc_packet(packet, size);
232 9706 : if (!packet)
233 : goto Memory_Error;
234 9706 : conn->recv_packet = packet;
235 : }
236 19412 : packet->data_len = size;
237 19412 : if (conn->recv_pos >= size) {
238 9706 : packet->data_start = sizeof(TDS72_SMP_HEADER);
239 9706 : packet->data_len -= sizeof(TDS72_SMP_HEADER);
240 9706 : 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 90219 : if (conn->recv_pos >= 8) {
248 83924 : len = TDS_GET_A2BE(&packet->buf[2]);
249 83924 : if (len < 8)
250 : goto Severe_Error;
251 83924 : if (packet->data_len < len) {
252 39113 : packet = tds_realloc_packet(packet, len);
253 39113 : if (!packet) goto Memory_Error;
254 39113 : conn->recv_packet = packet;
255 : }
256 83924 : packet->data_len = len;
257 83924 : 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 120 : 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 120 : p = mars;
277 120 : 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 120 : start = (char*) p - (char *) mars;
291 120 : packet = tds_get_packet(tds->conn, len + start);
292 120 : if (TDS_LIKELY(packet)) {
293 120 : packet->sid = tds->sid;
294 120 : memcpy(packet->buf, mars, start);
295 120 : memcpy(packet->buf + start, buf, len);
296 120 : packet->data_len = len + start;
297 : }
298 120 : return packet;
299 : }
300 :
301 : static void
302 : tds_append_packet(TDSPACKET **p_packet, TDSPACKET *packet)
303 : {
304 96849 : while (*p_packet)
305 364 : p_packet = &((*p_packet)->next);
306 96485 : *p_packet = packet;
307 : }
308 :
309 : int
310 120 : tds_append_cancel(TDSSOCKET *tds)
311 : {
312 : unsigned char buf[8];
313 : TDSPACKET *packet;
314 :
315 120 : buf[0] = TDS_CANCEL;
316 120 : buf[1] = 1;
317 120 : TDS_PUT_A2BE(buf+2, 8);
318 120 : TDS_PUT_A4(buf+4, 0);
319 120 : if (IS_TDS7_PLUS(tds->conn) && !tds->login)
320 89 : buf[6] = 0x01;
321 :
322 120 : packet = tds_build_packet(tds, buf, 8);
323 120 : if (!packet)
324 : return TDS_FAIL;
325 :
326 120 : tds_mutex_lock(&tds->conn->list_mtx);
327 240 : tds_append_packet(&tds->conn->send_packets, packet);
328 120 : tds_mutex_unlock(&tds->conn->list_mtx);
329 :
330 120 : return TDS_SUCCESS;
331 : }
332 :
333 :
334 : static void
335 96682 : tds_connection_network(TDSCONNECTION *conn, TDSSOCKET *tds, int send)
336 : {
337 96682 : assert(!conn->in_net_tds);
338 96682 : conn->in_net_tds = tds;
339 96682 : tds_mutex_unlock(&conn->list_mtx);
340 :
341 : for (;;) {
342 : /* wait packets or update */
343 172900 : int rc = tds_select(tds, conn->send_packets ? TDSSELREAD|TDSSELWRITE : TDSSELREAD, tds->query_timeout);
344 :
345 172900 : 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 172847 : 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 172694 : if (conn->send_packets && (rc & POLLOUT) != 0) {
372 : TDSSOCKET *s;
373 :
374 52874 : int sid = tds_packet_write(conn);
375 52874 : if (sid < 0)
376 5252 : continue;
377 :
378 47622 : 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 119820 : if (rc & (POLLIN|POLLHUP)) {
394 : TDSPACKET *packet;
395 : TDSSOCKET *s;
396 :
397 : /* try to read a packet */
398 119702 : if (!tds_packet_read(conn, tds))
399 70710 : continue; /* packet not complete */
400 48992 : packet = conn->recv_packet;
401 48992 : conn->recv_packet = NULL;
402 48992 : conn->recv_pos = 0;
403 :
404 48992 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Received packet", packet->buf, packet->data_start + packet->data_len);
405 :
406 48992 : tds_mutex_lock(&conn->list_mtx);
407 48992 : if (packet->sid < conn->num_sessions) {
408 48992 : s = conn->sessions[packet->sid];
409 48992 : if (TDSSOCKET_VALID(s)) {
410 : /* append to correct session */
411 48992 : if (packet->buf[0] == TDS72_SMP && packet->buf[1] != TDS_SMP_DATA)
412 172 : tds_packet_cache_add(conn, packet);
413 : else
414 48820 : tds_append_packet(&conn->packets, packet);
415 48992 : packet = NULL;
416 : /* notify */
417 48992 : tds_cond_signal(&s->packet_cond);
418 : }
419 : }
420 48992 : tds_mutex_unlock(&conn->list_mtx);
421 48992 : tds_free_packets(packet);
422 : /* if we are receiving return the packet */
423 48992 : if (!send) break;
424 : }
425 : }
426 :
427 96682 : tds_mutex_lock(&conn->list_mtx);
428 96682 : conn->in_net_tds = NULL;
429 96682 : }
430 :
431 : static TDSRET
432 46973 : tds_connection_put_packet(TDSSOCKET *tds, TDSPACKET *packet)
433 : {
434 46973 : TDSCONNECTION *conn = tds->conn;
435 :
436 46973 : CHECK_TDS_EXTRA(tds);
437 :
438 46973 : packet->sid = tds->sid;
439 :
440 46973 : tds_mutex_lock(&conn->list_mtx);
441 46973 : tds->sending_packet = packet;
442 94384 : while (tds->sending_packet) {
443 : int wait_res;
444 :
445 47411 : 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 47367 : if (packet && (int32_t) (tds->send_seq - tds->send_wnd) < 0) {
452 : /* prepare MARS header if needed */
453 46969 : if (tds->conn->mars) {
454 : TDS72_SMP_HEADER *hdr;
455 :
456 : /* fill SMP data */
457 9420 : hdr = (TDS72_SMP_HEADER *) packet->buf;
458 9420 : hdr->signature = TDS72_SMP;
459 9420 : hdr->type = TDS_SMP_DATA;
460 9420 : TDS_PUT_A2LE(&hdr->sid, packet->sid);
461 9420 : TDS_PUT_A4LE(&hdr->size, packet->data_start + packet->data_len);
462 9420 : ++tds->send_seq;
463 9420 : TDS_PUT_A4LE(&hdr->seq, tds->send_seq);
464 : /* this is the acknowledge we give to server to stop sending */
465 9420 : tds->recv_wnd = tds->recv_seq + 4;
466 9420 : TDS_PUT_A4LE(&hdr->wnd, tds->recv_wnd);
467 : }
468 :
469 : /* append packet */
470 93938 : tds_append_packet(&conn->send_packets, packet);
471 46969 : packet = NULL;
472 : }
473 :
474 : /* network ok ? process network */
475 47367 : if (!conn->in_net_tds) {
476 47367 : tds_connection_network(conn, tds, packet ? 0 : 1);
477 47367 : if (tds->sending_packet)
478 438 : 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 46973 : tds->sending_packet = NULL;
502 46973 : tds_mutex_unlock(&conn->list_mtx);
503 46973 : if (TDS_UNLIKELY(packet)) {
504 4 : tds_free_packets(packet);
505 4 : return TDS_FAIL;
506 : }
507 46969 : if (IS_TDSDEAD(tds))
508 : return TDS_FAIL;
509 46929 : 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 97551 : tds_read_packet(TDSSOCKET * tds)
522 : {
523 : #if ENABLE_ODBC_MARS
524 48858 : TDSCONNECTION *conn = tds->conn;
525 :
526 48858 : tds_mutex_lock(&conn->list_mtx);
527 :
528 : for (;;) {
529 : int wait_res;
530 : TDSPACKET **p_packet;
531 :
532 98173 : 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 98287 : for (p_packet = &conn->packets; *p_packet; p_packet = &(*p_packet)->next)
539 48972 : if ((*p_packet)->sid == tds->sid)
540 : break;
541 :
542 98135 : if (*p_packet) {
543 : /* remove our packet from list */
544 48820 : TDSPACKET *packet = *p_packet;
545 48820 : *p_packet = packet->next;
546 48820 : tds_packet_cache_add(conn, tds->recv_packet);
547 48820 : tds_mutex_unlock(&conn->list_mtx);
548 :
549 48820 : packet->next = NULL;
550 48820 : tds->recv_packet = packet;
551 :
552 48820 : tds->in_buf = packet->buf + packet->data_start;
553 48820 : tds->in_len = packet->data_len;
554 48820 : tds->in_pos = 8;
555 48820 : tds->in_flag = tds->in_buf[0];
556 :
557 : /* send acknowledge if needed */
558 48820 : if ((int32_t) (tds->recv_seq + 2 - tds->recv_wnd) >= 0)
559 347 : tds_update_recv_wnd(tds, tds->recv_seq + 4);
560 :
561 48820 : return tds->in_len;
562 : }
563 :
564 : /* network ok ? process network */
565 49315 : if (!conn->in_net_tds) {
566 49315 : tds_connection_network(conn, tds, 0);
567 49315 : 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 48693 : unsigned char *pkt = tds->in_buf, *p, *end;
587 :
588 48693 : if (IS_TDSDEAD(tds)) {
589 0 : tdsdump_log(TDS_DBG_NETWORK, "Read attempt when state is TDS_DEAD");
590 : return -1;
591 : }
592 :
593 48693 : tds->in_len = 0;
594 48693 : tds->in_pos = 0;
595 200368 : for (p = pkt, end = p+8; p < end;) {
596 103020 : ptrdiff_t len = tds_connection_read(tds, p, end - p);
597 103020 : if (len <= 0) {
598 38 : tds_close_socket(tds);
599 38 : return -1;
600 : }
601 :
602 102982 : p += len;
603 102982 : if (p - pkt >= 4) {
604 102982 : unsigned pktlen = TDS_GET_A2BE(pkt+2);
605 : /* packet must at least contains header */
606 102982 : if (TDS_UNLIKELY(pktlen < 8)) {
607 0 : tds_close_socket(tds);
608 0 : return -1;
609 : }
610 102982 : if (TDS_UNLIKELY(pktlen > tds->recv_packet->capacity)) {
611 1317 : TDSPACKET *packet = tds_realloc_packet(tds->recv_packet, pktlen);
612 1317 : if (TDS_UNLIKELY(!packet)) {
613 0 : tds_close_socket(tds);
614 0 : return -1;
615 : }
616 1317 : tds->recv_packet = packet;
617 1317 : pkt = packet->buf;
618 1317 : p = pkt + (p-tds->in_buf);
619 1317 : tds->in_buf = pkt;
620 : }
621 102982 : end = pkt + pktlen;
622 : }
623 : }
624 :
625 : /* set the received packet type flag */
626 48655 : tds->in_flag = pkt[0];
627 :
628 : /* Set the length and pos (not sure what pos is used for now */
629 48655 : tds->in_len = (unsigned int) (p - pkt);
630 48655 : tds->in_pos = 8;
631 48655 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Received packet", tds->in_buf, tds->in_len);
632 :
633 48655 : return tds->in_len;
634 : #endif /* !ENABLE_ODBC_MARS */
635 : }
636 :
637 : #if ENABLE_ODBC_MARS
638 : static TDSRET
639 347 : tds_update_recv_wnd(TDSSOCKET *tds, TDS_UINT new_recv_wnd)
640 : {
641 : TDS72_SMP_HEADER *mars;
642 : TDSPACKET *packet;
643 :
644 347 : if (!tds->conn->mars)
645 : return TDS_SUCCESS;
646 :
647 347 : packet = tds_get_packet(tds->conn, sizeof(*mars));
648 347 : if (!packet)
649 : return TDS_FAIL; /* TODO check result */
650 :
651 347 : packet->data_len = sizeof(*mars);
652 347 : packet->sid = tds->sid;
653 :
654 347 : mars = (TDS72_SMP_HEADER *) packet->buf;
655 347 : mars->signature = TDS72_SMP;
656 347 : mars->type = TDS_SMP_ACK;
657 347 : TDS_PUT_A2LE(&mars->sid, tds->sid);
658 347 : mars->size = TDS_HOST4LE(16);
659 347 : TDS_PUT_A4LE(&mars->seq, tds->send_seq);
660 347 : tds->recv_wnd = new_recv_wnd;
661 347 : TDS_PUT_A4LE(&mars->wnd, tds->recv_wnd);
662 :
663 347 : tds_mutex_lock(&tds->conn->list_mtx);
664 694 : tds_append_packet(&tds->conn->send_packets, packet);
665 347 : tds_mutex_unlock(&tds->conn->list_mtx);
666 :
667 347 : return TDS_SUCCESS;
668 : }
669 :
670 : static TDSRET
671 229 : tds_append_fin_syn(TDSSOCKET *tds, uint8_t type)
672 : {
673 : TDS72_SMP_HEADER mars;
674 : TDSPACKET *packet;
675 :
676 229 : if (!tds->conn->mars)
677 : return TDS_SUCCESS;
678 :
679 229 : mars.signature = TDS72_SMP;
680 229 : mars.type = type;
681 229 : TDS_PUT_A2LE(&mars.sid, tds->sid);
682 229 : mars.size = TDS_HOST4LE(16);
683 229 : TDS_PUT_A4LE(&mars.seq, tds->send_seq);
684 229 : tds->recv_wnd = tds->recv_seq + 4;
685 229 : TDS_PUT_A4LE(&mars.wnd, tds->recv_wnd);
686 :
687 : /* do not use tds_get_packet as it require no lock ! */
688 229 : packet = tds_alloc_packet(&mars, sizeof(mars));
689 229 : if (!packet)
690 : return TDS_FAIL; /* TODO check result */
691 229 : packet->sid = tds->sid;
692 :
693 : /* we already hold lock so do not lock */
694 458 : tds_append_packet(&tds->conn->send_packets, packet);
695 :
696 229 : 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 219 : tds_append_syn(TDSSOCKET *tds)
721 : {
722 : TDSRET ret;
723 219 : tds_mutex_lock(&tds->conn->list_mtx);
724 219 : ret = tds_append_fin_syn(tds, TDS_SMP_SYN);
725 219 : tds_mutex_unlock(&tds->conn->list_mtx);
726 219 : return ret;
727 : }
728 : #endif /* ENABLE_ODBC_MARS */
729 :
730 :
731 : TDS_COMPILE_CHECK(additional, TDS_ADDITIONAL_SPACE != 0);
732 :
733 : TDSRET
734 93315 : tds_write_packet(TDSSOCKET * tds, unsigned char final)
735 : {
736 : TDSRET res;
737 93315 : unsigned int left = 0;
738 93315 : TDSPACKET *pkt = tds->send_packet, *pkt_next = NULL;
739 :
740 93315 : CHECK_TDS_EXTRA(tds);
741 :
742 : #if !ENABLE_ODBC_MARS
743 46296 : if (tds->frozen)
744 : #endif
745 : {
746 47136 : pkt->next = pkt_next = tds_get_packet(tds->conn, pkt->capacity);
747 47136 : if (!pkt_next)
748 : return TDS_FAIL;
749 :
750 : #if ENABLE_ODBC_MARS
751 47019 : if (tds->conn->mars)
752 9444 : pkt_next->data_start = sizeof(TDS72_SMP_HEADER);
753 : #endif
754 : }
755 :
756 93315 : if (tds->out_pos > tds->out_buf_max) {
757 496 : left = tds->out_pos - tds->out_buf_max;
758 243 : if (pkt_next)
759 262 : memcpy(pkt_next->buf + tds_packet_get_data_start(pkt_next) + 8, tds->out_buf + tds->out_buf_max, left);
760 496 : 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 93315 : tds->out_buf[0] = tds->out_flag;
767 93315 : tds->out_buf[1] = final;
768 93315 : TDS_PUT_A2BE(tds->out_buf+2, tds->out_pos);
769 93315 : TDS_PUT_A2BE(tds->out_buf+4, tds->conn->client_spid);
770 93315 : TDS_PUT_A2(tds->out_buf+6, 0);
771 93315 : if (IS_TDS7_PLUS(tds->conn) && !tds->login)
772 65117 : tds->out_buf[6] = 0x01;
773 :
774 93315 : if (tds->frozen) {
775 334 : pkt->data_len = tds->out_pos;
776 334 : tds_set_current_send_packet(tds, pkt_next);
777 334 : tds->out_pos = left + 8;
778 334 : CHECK_TDS_EXTRA(tds);
779 334 : return TDS_SUCCESS;
780 : }
781 :
782 : #if ENABLE_ODBC_MARS
783 46802 : pkt->data_len = tds->out_pos;
784 46802 : pkt->next = NULL;
785 46802 : tds_set_current_send_packet(tds, pkt_next);
786 46802 : res = tds_connection_put_packet(tds, pkt);
787 : #else /* !ENABLE_ODBC_MARS */
788 46179 : 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 92358 : res = tds_connection_write(tds, tds->out_buf, tds->out_pos, final) <= 0 ?
792 46179 : TDS_FAIL : TDS_SUCCESS;
793 :
794 46179 : memcpy(tds->out_buf + 8, tds->out_buf + tds->out_buf_max, left);
795 : #endif /* !ENABLE_ODBC_MARS */
796 :
797 92981 : tds->out_pos = left + 8;
798 :
799 92981 : if (TDS_UNLIKELY(tds->conn->encrypt_single_packet)) {
800 730 : tds->conn->encrypt_single_packet = 0;
801 730 : tds_ssl_deinit(tds->conn);
802 : }
803 :
804 : return res;
805 : }
806 :
807 : #if !ENABLE_ODBC_MARS
808 : int
809 543 : tds_put_cancel(TDSSOCKET * tds)
810 : {
811 : unsigned char out_buf[8];
812 : ptrdiff_t sent;
813 :
814 543 : out_buf[0] = TDS_CANCEL; /* out_flag */
815 543 : out_buf[1] = 1; /* final */
816 543 : out_buf[2] = 0;
817 543 : out_buf[3] = 8;
818 543 : TDS_PUT_A4(out_buf+4, 0);
819 543 : if (IS_TDS7_PLUS(tds->conn) && !tds->login)
820 460 : out_buf[6] = 0x01;
821 :
822 543 : tdsdump_dump_buf(TDS_DBG_NETWORK, "Sending packet", out_buf, 8);
823 :
824 543 : sent = tds_connection_write(tds, out_buf, 8, 1);
825 :
826 543 : if (sent > 0)
827 537 : tds->in_cancel = 2;
828 :
829 : /* GW added in check for write() returning <0 and SIGPIPE checking */
830 543 : return sent <= 0 ? TDS_FAIL : TDS_SUCCESS;
831 : }
832 : #endif /* !ENABLE_ODBC_MARS */
833 :
834 :
835 : #if ENABLE_ODBC_MARS
836 : static int
837 52874 : tds_packet_write(TDSCONNECTION *conn)
838 : {
839 : int sent;
840 : int final;
841 52874 : TDSPACKET *packet = conn->send_packets;
842 :
843 52874 : assert(packet);
844 :
845 52874 : if (conn->send_pos == 0)
846 47662 : 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 52874 : if (packet->next != NULL)
850 : final = 0;
851 : /* take into account other packets for this session */
852 52592 : else if (packet->buf[0] != TDS72_SMP)
853 42816 : final = packet->buf[1] & 1;
854 : else
855 : final = 1;
856 :
857 52874 : sent = tds_connection_write(conn->in_net_tds, packet->buf + conn->send_pos,
858 52874 : packet->data_start + packet->data_len - conn->send_pos, final);
859 :
860 52874 : 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 52834 : conn->send_pos += sent;
868 : /* remove packet if sent all data */
869 52834 : if (conn->send_pos >= packet->data_start + packet->data_len) {
870 47622 : uint16_t sid = packet->sid;
871 : TDSSOCKET *tds;
872 47622 : tds_mutex_lock(&conn->list_mtx);
873 47622 : tds = conn->sessions[sid];
874 47622 : if (TDSSOCKET_VALID(tds) && tds->sending_packet == packet)
875 46929 : tds->sending_packet = NULL;
876 47622 : conn->send_packets = packet->next;
877 47622 : packet->next = NULL;
878 47622 : tds_packet_cache_add(conn, packet);
879 47622 : tds_mutex_unlock(&conn->list_mtx);
880 47622 : conn->send_pos = 0;
881 47622 : 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 79132 : tds_freeze(TDSSOCKET *tds, TDSFREEZE *freeze, unsigned size_len)
902 : {
903 79132 : CHECK_TDS_EXTRA(tds);
904 79132 : tds_extra_assert(size_len <= 4 && size_len != 3);
905 :
906 79132 : if (tds->out_pos > tds->out_buf_max)
907 15 : tds_write_packet(tds, 0x0);
908 :
909 79132 : if (!tds->frozen)
910 54561 : tds->frozen_packets = tds->send_packet;
911 :
912 79132 : ++tds->frozen;
913 79132 : freeze->tds = tds;
914 79132 : freeze->pkt = tds->send_packet;
915 79132 : freeze->pkt_pos = tds->out_pos;
916 79132 : freeze->size_len = size_len;
917 79132 : if (size_len)
918 73398 : tds_put_n(tds, NULL, size_len);
919 :
920 79132 : CHECK_FREEZE_EXTRA(freeze);
921 79132 : }
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 69460 : tds_freeze_written(TDSFREEZE *freeze)
930 : {
931 69460 : TDSSOCKET *tds = freeze->tds;
932 69460 : TDSPACKET *pkt = freeze->pkt;
933 : unsigned int size;
934 :
935 69460 : CHECK_FREEZE_EXTRA(freeze);
936 :
937 : /* last packet needs special handling */
938 69460 : size = tds->out_pos;
939 :
940 : /* packets before last */
941 69842 : for (; pkt->next != NULL; pkt = pkt->next)
942 382 : size += pkt->data_len - 8;
943 :
944 69460 : 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 23752 : tds_freeze_close(TDSFREEZE *freeze)
991 : {
992 23752 : 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 14068 : tds_freeze_close_string(TDSFREEZE *freeze)
1007 : {
1008 14068 : size_t written = tds_freeze_written(freeze) - freeze->size_len;
1009 14068 : if (IS_TDS7_PLUS(freeze->tds->conn))
1010 14068 : written /= 2;
1011 14068 : 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 73368 : unsigned pos = freeze->pkt_pos;
1019 73368 : unsigned size_len = freeze->size_len;
1020 :
1021 73368 : pkt = freeze->pkt;
1022 : do {
1023 234758 : if (pos >= pkt->data_len && pkt->next) {
1024 15 : pkt = pkt->next;
1025 15 : pos = 8;
1026 : }
1027 234758 : pkt->buf[tds_packet_get_data_start(pkt) + pos] = size & 0xffu;
1028 234758 : size >>= 8;
1029 234758 : pos++;
1030 234758 : } 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 79102 : tds_freeze_close_len(TDSFREEZE *freeze, int32_t size)
1045 : {
1046 79102 : TDSSOCKET *tds = freeze->tds;
1047 : TDSPACKET *pkt;
1048 : #if !ENABLE_ODBC_MARS
1049 39437 : TDSPACKET *last_pkt_sent = NULL;
1050 : #endif
1051 :
1052 79102 : CHECK_FREEZE_EXTRA(freeze);
1053 :
1054 79102 : if (freeze->size_len)
1055 73368 : tds_freeze_update_size(freeze, size);
1056 :
1057 : /* if not last freeze we need just to update size */
1058 79102 : freeze->tds = NULL;
1059 79102 : if (--tds->frozen != 0)
1060 : return TDS_SUCCESS;
1061 :
1062 54531 : tds->frozen_packets = NULL;
1063 54531 : pkt = freeze->pkt;
1064 109297 : while (pkt->next) {
1065 262 : TDSPACKET *next = pkt->next;
1066 : TDSRET rc;
1067 : #if ENABLE_ODBC_MARS
1068 171 : pkt->next = NULL;
1069 171 : freeze->pkt = next;
1070 : /* packet will get owned by function, no need to release it */
1071 171 : rc = tds_connection_put_packet(tds, pkt);
1072 : #else
1073 182 : rc = tds_connection_write(tds, pkt->buf, pkt->data_len, 0) <= 0 ?
1074 91 : TDS_FAIL : TDS_SUCCESS;
1075 91 : last_pkt_sent = pkt;
1076 : #endif
1077 262 : 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 54504 : tds_extra_assert(pkt->next == NULL);
1095 54504 : tds_extra_assert(pkt == tds->send_packet);
1096 :
1097 : #if !ENABLE_ODBC_MARS
1098 27159 : if (last_pkt_sent) {
1099 33 : tds_extra_assert(last_pkt_sent->next == pkt);
1100 33 : last_pkt_sent->next = NULL;
1101 33 : tds_mutex_lock(&tds->conn->list_mtx);
1102 33 : tds_packet_cache_add(tds->conn, freeze->pkt);
1103 33 : tds_mutex_unlock(&tds->conn->list_mtx);
1104 : }
1105 : #endif
1106 :
1107 : /* keep final packet so we can continue to add data */
1108 27345 : return TDS_SUCCESS;
1109 : }
1110 :
1111 : /** @} */
|