00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "vsl.h"
00017 #include "vfer.h"
00018 #include "vsl_api.h"
00019 #include "vsl_util.h"
00020 #include "vsl_ssh.h"
00021 #include "../poly1305aes/poly1305aes.h"
00022 #include <sys/types.h>
00023 #include <signal.h>
00024 #include <sys/wait.h>
00025
00026
00027
00028
00029
00030
00031
00032 int vsl_init(void) {
00033 return 0;
00034 }
00035
00036
00037
00038
00039
00040
00041
00042
00043 int vsl_uninit(void) {
00044 return 0;
00045 }
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 int vsl_connect_ssh (vsl_sock* socket, const char* host, const char* user,
00088 const char* cmd, int argc, const char* const *argv,
00089 char* errmsg) {
00090 unsigned char secret[VSL_KEYLEN];
00091 int port, ret;
00092
00093 LOG("trying ssh startup as client");
00094
00095 switch(CONSTAT(socket->status)) {
00096 case(C_INITIALIZED):
00097
00098 TRY(ssh_fork(socket, host, user, cmd, argc, argv));
00099
00100
00101 TRY(gen_key(secret));
00102
00103
00104 socket->status = C_SSH_FORKED | C_WAIT_FD_W;
00105
00106
00107 if ( socket->test_mode &&
00108 !is_blocking(socket) )
00109 LOGFAIL(VFER_INPROGRESS, "returning, testing mode.");
00110
00111 case(C_SSH_FORKED):
00112
00113 if ( (ret=ssh_send_secret(socket, secret)) != 0) {
00114 int bak = errno;
00115 ssh_close(socket, errmsg);
00116 errno = bak;
00117 return ret;
00118 }
00119
00120
00121 socket->status = C_SSH_WROTE_SEC | C_WAIT_FD_R;
00122
00123
00124 if ( socket->test_mode &&
00125 !is_blocking(socket) )
00126 LOGFAIL(VFER_INPROGRESS, "returning, testing mode.");
00127
00128 case(C_SSH_WROTE_SEC):
00129
00130 if ( (ret=ssh_read_port(socket, &port)) != 0) {
00131 int bak = errno;
00132 ssh_close(socket, errmsg);
00133 errno = bak;
00134 return ret;
00135 }
00136
00137
00138 TRY(ssh_vfer_connect(socket, host, port));
00139 socket->status = C_SSH_VF_CON | C_WAIT_PID;
00140
00141
00142 if ( socket->test_mode &&
00143 !is_blocking(socket) )
00144 LOGFAIL(VFER_INPROGRESS, "returning, testing mode.");
00145
00146 case C_SSH_VF_CON:
00147
00148 TRY(ssh_close(socket, errmsg));
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 init_keys_c(socket, secret);
00170
00171 socket->status = C_ESTABLISHED;
00172 socket->auth = VSL_AUTH_SSH;
00173 break;
00174
00175 default:
00176
00177 LOGFAIL(VFER_BADSOCK, "invalid socket state");
00178 }
00179
00180 LOG("ssh startup successful.");
00181 return 0;
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 int vsl_accept_ssh (vsl_sock* socket) {
00212 int port;
00213 unsigned char secret[VSL_KEYLEN];
00214
00215 LOG("attempting ssh startup as server...");
00216
00217 TRY(ssh_read_secret(secret));
00218 TRY(ssh_vfer_listen(socket, &port));
00219 TRY(ssh_send_port(port));
00220 TRY(ssh_vfer_accept(socket));
00221 TRY(ssh_daemonize());
00222
00223 init_keys_s(socket, secret);
00224
00225 socket->status = C_ESTABLISHED;
00226 socket->auth = VSL_AUTH_SSH;
00227
00228 LOG("ssh startup successful.");
00229 return 0;
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 int vsl_socket(vsl_sock* socket, const vfer_fd fd) {
00245
00246 LOG("initializing socket...");
00247
00248 socket->vfd = fd;
00249 socket->status = C_INITIALIZED;
00250 socket->sent_nr = 1;
00251 socket->recv_nr = 0;
00252 socket->test_mode = false;
00253
00254
00255 int nonblocking = 0;
00256 int ret = sizeof(int);
00257 int tmp;
00258 if ( (tmp=vfer_getsockopt(socket->vfd, VFERSO_NONBLOCK, &nonblocking, &ret))
00259 == VFER_BADSOCK )
00260 LOGFAIL(tmp, "received invalid vfer socket!");
00261 else if ( tmp != 0 )
00262 LOGFATAL("vfer_getsockopt failed: %s!", vfer_errortext(tmp));
00263
00264
00265 LOG("socket initialized.");
00266 return 0;
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 void vsl_close (vsl_sock* sock) {
00283 LOG("closed vsl socket.");
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 vfer_fd vsl_vferfd(vsl_sock* socket) {
00295 return socket->vfd;
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 ssize_t vsl_max_frame_size(vsl_sock* socket) {
00307 return ( (vfer_max_frame_size(socket->vfd) > 1024*1024*1024 ?
00308 1024*1024*1024 :
00309 vfer_max_frame_size(socket->vfd)) - PHEAD_SIZE);
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 ssize_t vsl_send(vsl_sock* sock, const void * buf, size_t len) {
00343 LOG("attempting to send %zd bytes...", len);
00344
00345
00346 if ( !is_blocking(sock) &&
00347 vfer_is_stream(sock->vfd) )
00348 LOGFAIL(VFER_INVAL, "nonblocking IO not supported for streamed connections!");
00349
00350
00351
00352 if ( sock->sent_nr == 0 )
00353 LOGFAIL(VSL_MAXMSG, "maximum message count reached!");
00354
00355
00356 if ( len > vsl_max_frame_size(sock) )
00357 LOGFAIL(VSL_TOOBIG, "Message too large.");
00358
00359
00360 phead_t msg;
00361 msg.type = P_DATA;
00362 FILL_MAGIC(msg.magic);
00363 msg.datalen = htonl(len);
00364 msg.msgnr = htonll(sock->sent_nr++);
00365
00366
00367 size_t buflen;
00368 unsigned char *sbuf;
00369 if ( (sbuf = write_objs(&buflen,
00370 (void*) &msg.msgnr, sizeof(msg.msgnr),
00371 (void*) &msg.hash, sizeof(msg.hash),
00372 (void*) &msg.magic, sizeof(msg.magic),
00373 (void*) &msg.type, sizeof(msg.type),
00374 (void*) &msg.datalen, sizeof(msg.datalen),
00375 buf, len, NULL)) == NULL)
00376 LOGFAIL(VSL_ERRNO, "malloc failed: %s", strerror(err));
00377
00378
00379 LOG("encrypting...");
00380 unsigned char ctr[16];
00381 memset((void*) ctr, 0, 16);
00382 memcpy((void*) ctr, (void*) sbuf, sizeof(msg.msgnr));
00383 aes_ctr(ctr, sock->enc_send_key, sbuf + PHEAD_SIZE, len);
00384
00385
00386 LOG("Calculating MAC...");
00387 unsigned char hash[sizeof(msg.hash)];
00388 memset((void*) ctr, 0, 16);
00389 memcpy((void*) ctr, (void*) sbuf, sizeof(msg.msgnr));
00390 memset(sbuf + sizeof(msg.msgnr), 0, sizeof(msg.hash));
00391 poly1305aes_authenticate(hash, sock->auth_send_key, ctr,
00392 sbuf, buflen);
00393 memcpy(sbuf + sizeof(msg.msgnr), hash, sizeof(msg.hash));
00394
00395
00396
00397 LOG("Sending total message of size %zd bytes.", buflen);
00398 int ret;
00399 if ( (ret=transfer(sock, (transmit_fn) vfer_send, sbuf, buflen, buflen)) < 0) {
00400 free(sbuf);
00401 return ret;
00402 }
00403 free(sbuf);
00404
00405 LOG("message sent.");
00406 return len;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 ssize_t vsl_sendfile(vsl_sock* sock, int fd, off_t offset, size_t len) {
00432 return vfer__sendfile( (vfer_trnsm_fn) vsl_send, (vfer_trnsm_arg) sock,
00433 vsl_max_frame_size(sock),fd, offset, len );
00434 }
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 ssize_t vsl_recv(vsl_sock* sock, void *buf, size_t len) {
00470 unsigned char* rbuf;
00471 size_t to_read;
00472
00473
00474 if ( !is_blocking(sock) &&
00475 vfer_is_stream(sock->vfd) )
00476 LOGFAIL(VFER_INVAL, "nonblocking IO not supported for streamed connections!");
00477
00478
00479
00480 if ( (rbuf = malloc(vfer_max_frame_size(sock->vfd))) == NULL)
00481 LOGFAIL(VSL_ERRNO, "malloc failed: %s", strerror(err));
00482
00483
00484 if ( vfer_is_stream(sock->vfd) ) {
00485 LOG("retrieving header...");
00486 to_read = PHEAD_SIZE;
00487 }
00488 else {
00489 LOG("trying to retrieve %zd + %zd bytes (body+header)...",
00490 len, PHEAD_SIZE);
00491 to_read = len + PHEAD_SIZE;
00492 }
00493
00494
00495 ssize_t rcnt;
00496 if ( (rcnt=transfer(sock, (transmit_fn) vfer_recv, rbuf, PHEAD_SIZE, to_read)) < 0) {
00497 free(rbuf);
00498 return rcnt;
00499 }
00500
00501
00502 phead_t head;
00503 unsigned char* body;
00504 if ( (body = read_objs(rbuf, rcnt,
00505 (void*) &head.msgnr, sizeof(head.msgnr),
00506 (void*) &head.hash, sizeof(head.hash),
00507 (void*) &head.magic, sizeof(head.magic),
00508 (void*) &head.type, sizeof(head.type),
00509 (void*) &head.datalen, sizeof(head.datalen),
00510 NULL)) == NULL ) {
00511
00512 free(rbuf);
00513 LOGFATAL("message too short!");
00514 }
00515 head.datalen = ntohl(head.datalen);
00516 LOG("actual body length %zd bytes.", head.datalen);
00517
00518
00519 if ( vfer_is_stream(sock->vfd) ) {
00520 LOG("retrieving body...");
00521 if ( (rcnt = transfer(sock, (transmit_fn) vfer_recv, body, head.datalen, head.datalen)) < 0 ) {
00522 free(rbuf);
00523 return rcnt;
00524 }
00525 }
00526
00527
00528 else if ( head.datalen != rcnt - PHEAD_SIZE ) {
00529 free(rbuf);
00530 LOGFAIL(VSL_BADPROT, "invalid message received (too short)!");
00531 }
00532
00533
00534 if ( head.datalen > len ) {
00535 free(rbuf);
00536 LOGFAIL(VSL_TOOBIG, "message does not fit into given buf!");
00537 }
00538
00539
00540 if ( head.datalen > vsl_max_frame_size(sock) ) {
00541 free(rbuf);
00542 LOGFAIL(VSL_BADPROT, "invalid message received (too long)!");
00543 }
00544
00545
00546 if ( !CHECK_MAGIC(head.magic) ) {
00547 free(rbuf);
00548 LOGFAIL(VSL_BADPROT, "invalid message received (wrong magic)!");
00549 }
00550
00551
00552 if ( head.type != P_DATA ) {
00553 free(rbuf);
00554 LOGFAIL(VSL_BADPROT, "invalid message received (wrong type)!");
00555 }
00556
00557
00558 if ( ntohll(head.msgnr) <= sock->recv_nr ) {
00559 free(rbuf);
00560 LOGFAIL(VSL_BADPROT, "invalid message received (old msgnr)!");
00561 }
00562 sock->recv_nr = ntohll(head.msgnr);
00563
00564
00565 LOG("Checking MAC...");
00566 unsigned char ctr[16];
00567 memset((void*) ctr, 0, 16);
00568 memcpy((void*) ctr, (void*) rbuf, sizeof(head.msgnr));
00569 memset(rbuf + sizeof(head.msgnr), 0, sizeof(head.hash));
00570 if ( poly1305aes_verify(head.hash, sock->auth_recv_key, ctr,
00571 rbuf, head.datalen + PHEAD_SIZE) == 0 ) {
00572 free(rbuf);
00573 LOGFAIL(VSL_BADPROT, "invalid message received (wrong MAC)!");
00574 }
00575
00576
00577 LOG("Decrypting body...");
00578 memset((void*) ctr, 0, 16);
00579 memcpy((void*) ctr, (void*) rbuf, sizeof(head.msgnr));
00580 aes_ctr(ctr, sock->enc_recv_key, body, head.datalen);
00581
00582
00583 memcpy(buf, body, head.datalen);
00584 free(rbuf);
00585
00586 LOG("message received.");
00587 return head.datalen;
00588 }
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609 ssize_t vsl_recvfile(vsl_sock* sock, int fd, off_t offset, size_t len) {
00610 return vfer__recvfile( (vfer_trnsm_fn) vsl_recv, (vfer_trnsm_arg) sock,
00611 vsl_max_frame_size(sock),fd, offset, len);
00612 }
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631 int vsl_selectmark(vsl_sock* socket, int mark) {
00632 LOG("entered.");
00633 if ((mark & ~(VSL_READABLE | VSL_WRITABLE | VSL_EXCEPTION | VSL_AUTHABLE)) != 0)
00634 LOGFAIL(VFER_INVAL, "invalid mark value!");
00635
00636 socket->selectmark = mark;
00637 LOG("marked socket.");
00638 return 0;
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 int vsl_selecttest(vsl_sock* sock) {
00654 return sock->selectres;
00655 }
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683 int vsl_select(int len, vsl_sock** socks, struct timeval *stimeout) {
00684 LOG("entered.");
00685
00686 vfer_fd vfer_fds[len];
00687 fd_set read_fds, write_fds, except_fds;
00688 int vfer_fd_count=0,
00689 file_fd_count=-1,
00690 pid_count=0;
00691
00692 FD_ZERO(&read_fds);
00693 FD_ZERO(&write_fds);
00694 FD_ZERO(&except_fds);
00695
00696
00697 for (int i=0; i < len; i++) {
00698 vsl_sock* sock = socks[i];
00699 sock->selectres = 0;
00700
00701
00702
00703 if ( sock->status == C_ESTABLISHED ) {
00704 int mark = 0, ret;
00705 mark |= VSL_READABLE & sock->selectmark ? VFER_READABLE : 0;
00706 mark |= VSL_WRITABLE & sock->selectmark ? VFER_WRITABLE : 0;
00707 mark |= VSL_EXCEPTION & sock->selectmark ? VFER_EXCEPTION : 0;
00708 if ((ret=vfer_selectmark(sock->vfd, mark)) < 0)
00709 LOGFATAL("unknown vfer error: %s", vfer_errortext(ret));
00710 vfer_fds[vfer_fd_count++] = sock->vfd;
00711 LOG("adding socket to vfer select list.");
00712 continue;
00713 }
00714
00715
00716
00717 if ( sock->selectmark & VSL_AUTHABLE ) {
00718 int ret;
00719
00720
00721 if (sock->status == C_INITIALIZED) {
00722 sock->selectres = VSL_AUTHABLE;
00723 LOGFAIL(1, "socket in initialized state, returning now.");
00724 }
00725
00726 switch (CONWAIT(sock->status)) {
00727
00728 case C_WAIT_FD_R:
00729
00730 FD_SET(sock->ssh_stdout_fd, &read_fds);
00731 FD_SET(sock->ssh_stdout_fd, &except_fds);
00732 LOG("adding socket to read fd set.");
00733 if ( sock->ssh_stdout_fd > file_fd_count )
00734 file_fd_count = sock->ssh_stdout_fd;
00735 continue;
00736
00737 case C_WAIT_FD_W:
00738
00739 FD_SET(sock->ssh_stdin_fd, &write_fds);
00740 FD_SET(sock->ssh_stdin_fd, &except_fds);
00741 LOG("adding socket to write fd set.");
00742 if ( sock->ssh_stdin_fd > file_fd_count )
00743 file_fd_count = sock->ssh_stdin_fd;
00744 continue;
00745
00746 case C_WAIT_PID:
00747
00748 if ( sock->ssh_pid == 0 )
00749 LOGFAIL(1, "already waited for pid, returning now.");
00750 pid_count++;
00751 LOG("adding socket to pid wait set.");
00752 continue;
00753
00754 case C_WAIT_VFD_R:
00755
00756 if ((ret=vfer_selectmark(sock->vfd, VFER_READABLE | VFER_EXCEPTION)) < 0)
00757 LOGFATAL("unknown vfer error: %s", vfer_errortext(ret));
00758 vfer_fds[vfer_fd_count++] = sock->vfd;
00759 LOG("adding socket to vfer select list.");
00760 continue;
00761
00762
00763 case C_WAIT_VFD_W:
00764
00765 if ((ret=vfer_selectmark(sock->vfd, VFER_WRITABLE | VFER_EXCEPTION)) < 0)
00766 LOGFATAL("unknown vfer error: %s", vfer_errortext(ret));
00767 vfer_fds[vfer_fd_count++] = sock->vfd;
00768 LOG("adding socket to vfer select list.");
00769 continue;
00770
00771 }
00772 }
00773 }
00774 file_fd_count++;
00775
00776
00777
00778 struct timeval *timeout;
00779 if ( (vfer_fd_count != 0 &&
00780 file_fd_count != 0) ||
00781 (vfer_fd_count != 0 &&
00782 pid_count != 0) ||
00783 (file_fd_count != 0 &&
00784 pid_count != 0) ) {
00785 LOG("polling neccessary.");
00786 timeout = &((struct timeval) { 0, 0 });
00787 }
00788 else {
00789 LOG("no polling neccessary.");
00790 timeout = stimeout;
00791 }
00792
00793
00794
00795 int ret, cnt=0;
00796 if (vfer_fd_count) {
00797 LOG("calling vfer_select...");
00798 if ( (cnt = vfer_select(vfer_fd_count, vfer_fds, timeout)) == -1 )
00799 LOGFAIL(VSL_ERRNO, "vfer_select failed: %s!", vfer_errortext(cnt));
00800 LOG("%d sockets ready so far..", cnt);
00801
00802
00803 for(int i=0; i < len; i++) {
00804 vsl_sock* sock = socks[i];
00805 if ( sock->status == C_ESTABLISHED ) {
00806 if ( (ret = vfer_selecttest(sock->vfd)) < 0)
00807 LOGFATAL("unknown vfer error: %s", vfer_errortext(ret));
00808 if ( ret & VFER_READABLE )
00809 sock->selectres |= VSL_READABLE;
00810 if ( ret & VFER_WRITABLE )
00811 sock->selectres |= VSL_WRITABLE;
00812 if ( ret & VFER_EXCEPTION )
00813 sock->selectres |= VSL_EXCEPTION;
00814 }
00815
00816
00817 if ( sock->selectmark & VSL_AUTHABLE &&
00818 ( CONWAIT(sock->status) == C_WAIT_VFD_W ||
00819 CONWAIT(sock->status) == C_WAIT_VFD_R ) ) {
00820 if ( (ret = vfer_selecttest(sock->vfd)) < 0)
00821 LOGFATAL("unknown vfer error: %s", vfer_errortext(ret));
00822 if (ret)
00823 sock->selectres |= VSL_AUTHABLE;
00824 }
00825 }
00826 }
00827
00828
00829
00830 if (file_fd_count) {
00831 LOG("calling select...");
00832 if ( (cnt += select(file_fd_count, &read_fds, &write_fds, &except_fds,
00833 timeout)) == -1)
00834 LOGFAIL(VSL_ERRNO, "select call failed: %s!", strerror(errno));
00835 LOG("%d sockets ready so far..", cnt);
00836
00837
00838 for(int i=0; i < len; i++) {
00839 vsl_sock* sock = socks[i];
00840 if ( sock->selectmark & VSL_AUTHABLE &&
00841 CONWAIT(sock->status) == C_WAIT_FD_W )
00842 if ( FD_ISSET(sock->ssh_stdin_fd, &write_fds) ||
00843 FD_ISSET(sock->ssh_stdin_fd, &except_fds) )
00844 sock->selectres |= VSL_AUTHABLE;
00845
00846 if ( sock->selectmark & VSL_AUTHABLE &&
00847 CONWAIT(sock->status) == C_WAIT_FD_R )
00848 if ( FD_ISSET(sock->ssh_stdout_fd, &read_fds) ||
00849 FD_ISSET(sock->ssh_stdout_fd, &except_fds) )
00850 sock->selectres |= VSL_AUTHABLE;
00851 }
00852
00853 }
00854
00855
00856
00857 if (pid_count) {
00858 LOG("Checking PIDs...");
00859 for(int i=0; i < len; i++) {
00860 vsl_sock* sock = socks[i];
00861 if ( (sock->selectmark & VSL_AUTHABLE) &&
00862 CONWAIT(sock->status) == C_WAIT_PID) {
00863 LOG("trying to wait for pid %d..", sock->ssh_pid);
00864
00865
00866 if( waitpid(sock->ssh_pid, &(sock->ssh_pid_stat), WNOHANG) > 0) {
00867 LOG("successful.");
00868 sock->ssh_pid = 0;
00869 cnt++;
00870 sock->selectres |= VSL_AUTHABLE;
00871 }
00872 else
00873 LOG("still running.");
00874 }
00875 }
00876 LOG("%d sockets ready so far..", cnt);
00877 }
00878
00879
00880 LOG("returning.");
00881 if (timeout == stimeout || cnt)
00882 return cnt;
00883 else
00884 return VFER_INPROGRESS;
00885 }
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898 char* vsl_errortext(int err) {
00899 switch (err) {
00900 case VSL_BADPROT:
00901 return "protocol error or forged message";
00902 case VSL_MAXMSG:
00903 return "maximum message count exceeded";
00904 case VSL_ERRNO:
00905 return strerror(errno);
00906 case VSL_SSHF:
00907 return "ssh subprocess failed";
00908 case VSL_TEMP:
00909 return "server signaled temporary error";
00910 case VSL_PERM:
00911 return "server signaled permanent error";
00912 case VSL_TOOBIG:
00913 return "message too big";
00914 default:
00915 return vfer_errortext(err);
00916 }
00917 }
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929 FILE* debug = NULL;
00930 void vsl_debug (FILE* fp, const char* vfer) {
00931
00932 if (fp == NULL) {
00933 debug = NULL;
00934 vfer_debug(NULL, NULL, "");
00935 return;
00936 }
00937
00938
00939 int fd;
00940 if ( (fd = dup(fileno(fp))) == -1 ) {
00941 fprintf(stderr, "Cannot dup fd: %s!\n", strerror(errno));
00942 abort();
00943 }
00944 if ( (debug = fdopen(fd, "a")) == NULL ) {
00945 fprintf(stderr, "Cannot fdopen fd %d: %s!\n", fd, strerror(errno));
00946 abort();
00947 }
00948 if (vfer == NULL)
00949 vfer = "";
00950 vfer_debug(debug, debug, vfer);
00951 }
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961 void vsl_test_mode(vsl_sock* sock) {
00962 LOG("Activating test mode.");
00963 sock->test_mode = true;
00964 }
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 int vsl_selectpoll(int len, vsl_sock** socks, struct timeval *stimeout, int usec) {
00980 int ret;
00981 struct timeval start;
00982 struct timeval now;
00983 GET_TIME_OF_DAY(&start);
00984 do {
00985 ret = vsl_select(len, socks, stimeout);
00986 if ( ret == VFER_INPROGRESS ) {
00987 GET_TIME_OF_DAY(&now);
00988 if ( TIMEVAL_MS(*stimeout) > TIMEVAL_MS_DIFF(start, now) )
00989 return 0;
00990 usleep(usec);
00991 continue;
00992 }
00993 else
00994 return ret;
00995 } while(1);
00996 }
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007