1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel (at) haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 23 #include "curl_setup.h" 24 25 #ifndef CURL_DISABLE_TELNET 26 27 #ifdef HAVE_NETINET_IN_H 28 #include <netinet/in.h> 29 #endif 30 #ifdef HAVE_NETDB_H 31 #include <netdb.h> 32 #endif 33 #ifdef HAVE_ARPA_INET_H 34 #include <arpa/inet.h> 35 #endif 36 #ifdef HAVE_NET_IF_H 37 #include <net/if.h> 38 #endif 39 #ifdef HAVE_SYS_IOCTL_H 40 #include <sys/ioctl.h> 41 #endif 42 43 #ifdef HAVE_SYS_PARAM_H 44 #include <sys/param.h> 45 #endif 46 47 #include "urldata.h" 48 #include <curl/curl.h> 49 #include "transfer.h" 50 #include "sendf.h" 51 #include "telnet.h" 52 #include "connect.h" 53 #include "progress.h" 54 #include "system_win32.h" 55 56 #define TELOPTS 57 #define TELCMDS 58 59 #include "arpa_telnet.h" 60 #include "select.h" 61 #include "strequal.h" 62 #include "rawstr.h" 63 #include "warnless.h" 64 65 /* The last 3 #include files should be in this order */ 66 #include "curl_printf.h" 67 #include "curl_memory.h" 68 #include "memdebug.h" 69 70 #define SUBBUFSIZE 512 71 72 #define CURL_SB_CLEAR(x) x->subpointer = x->subbuffer 73 #define CURL_SB_TERM(x) \ 74 do { \ 75 x->subend = x->subpointer; \ 76 CURL_SB_CLEAR(x); \ 77 } WHILE_FALSE 78 #define CURL_SB_ACCUM(x,c) \ 79 do { \ 80 if(x->subpointer < (x->subbuffer+sizeof x->subbuffer)) \ 81 *x->subpointer++ = (c); \ 82 } WHILE_FALSE 83 84 #define CURL_SB_GET(x) ((*x->subpointer++)&0xff) 85 #define CURL_SB_PEEK(x) ((*x->subpointer)&0xff) 86 #define CURL_SB_EOF(x) (x->subpointer >= x->subend) 87 #define CURL_SB_LEN(x) (x->subend - x->subpointer) 88 89 #ifdef CURL_DISABLE_VERBOSE_STRINGS 90 #define printoption(a,b,c,d) Curl_nop_stmt 91 #endif 92 93 #ifdef USE_WINSOCK 94 typedef FARPROC WSOCK2_FUNC; 95 static CURLcode check_wsock2 (struct Curl_easy *data); 96 #endif 97 98 static 99 CURLcode telrcv(struct connectdata *, 100 const unsigned char *inbuf, /* Data received from socket */ 101 ssize_t count); /* Number of bytes received */ 102 103 #ifndef CURL_DISABLE_VERBOSE_STRINGS 104 static void printoption(struct Curl_easy *data, 105 const char *direction, 106 int cmd, int option); 107 #endif 108 109 static void negotiate(struct connectdata *); 110 static void send_negotiation(struct connectdata *, int cmd, int option); 111 static void set_local_option(struct connectdata *, int cmd, int option); 112 static void set_remote_option(struct connectdata *, int cmd, int option); 113 114 static void printsub(struct Curl_easy *data, 115 int direction, unsigned char *pointer, 116 size_t length); 117 static void suboption(struct connectdata *); 118 static void sendsuboption(struct connectdata *conn, int option); 119 120 static CURLcode telnet_do(struct connectdata *conn, bool *done); 121 static CURLcode telnet_done(struct connectdata *conn, 122 CURLcode, bool premature); 123 static CURLcode send_telnet_data(struct connectdata *conn, 124 char *buffer, ssize_t nread); 125 126 /* For negotiation compliant to RFC 1143 */ 127 #define CURL_NO 0 128 #define CURL_YES 1 129 #define CURL_WANTYES 2 130 #define CURL_WANTNO 3 131 132 #define CURL_EMPTY 0 133 #define CURL_OPPOSITE 1 134 135 /* 136 * Telnet receiver states for fsm 137 */ 138 typedef enum 139 { 140 CURL_TS_DATA = 0, 141 CURL_TS_IAC, 142 CURL_TS_WILL, 143 CURL_TS_WONT, 144 CURL_TS_DO, 145 CURL_TS_DONT, 146 CURL_TS_CR, 147 CURL_TS_SB, /* sub-option collection */ 148 CURL_TS_SE /* looking for sub-option end */ 149 } TelnetReceive; 150 151 struct TELNET { 152 int please_negotiate; 153 int already_negotiated; 154 int us[256]; 155 int usq[256]; 156 int us_preferred[256]; 157 int him[256]; 158 int himq[256]; 159 int him_preferred[256]; 160 int subnegotiation[256]; 161 char subopt_ttype[32]; /* Set with suboption TTYPE */ 162 char subopt_xdisploc[128]; /* Set with suboption XDISPLOC */ 163 unsigned short subopt_wsx; /* Set with suboption NAWS */ 164 unsigned short subopt_wsy; /* Set with suboption NAWS */ 165 struct curl_slist *telnet_vars; /* Environment variables */ 166 167 /* suboptions */ 168 unsigned char subbuffer[SUBBUFSIZE]; 169 unsigned char *subpointer, *subend; /* buffer for sub-options */ 170 171 TelnetReceive telrcv_state; 172 }; 173 174 175 /* 176 * TELNET protocol handler. 177 */ 178 179 const struct Curl_handler Curl_handler_telnet = { 180 "TELNET", /* scheme */ 181 ZERO_NULL, /* setup_connection */ 182 telnet_do, /* do_it */ 183 telnet_done, /* done */ 184 ZERO_NULL, /* do_more */ 185 ZERO_NULL, /* connect_it */ 186 ZERO_NULL, /* connecting */ 187 ZERO_NULL, /* doing */ 188 ZERO_NULL, /* proto_getsock */ 189 ZERO_NULL, /* doing_getsock */ 190 ZERO_NULL, /* domore_getsock */ 191 ZERO_NULL, /* perform_getsock */ 192 ZERO_NULL, /* disconnect */ 193 ZERO_NULL, /* readwrite */ 194 PORT_TELNET, /* defport */ 195 CURLPROTO_TELNET, /* protocol */ 196 PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ 197 }; 198 199 200 #ifdef USE_WINSOCK 201 static CURLcode 202 check_wsock2(struct Curl_easy *data) 203 { 204 int err; 205 WORD wVersionRequested; 206 WSADATA wsaData; 207 208 DEBUGASSERT(data); 209 210 /* telnet requires at least WinSock 2.0 so ask for it. */ 211 wVersionRequested = MAKEWORD(2, 0); 212 213 err = WSAStartup(wVersionRequested, &wsaData); 214 215 /* We must've called this once already, so this call */ 216 /* should always succeed. But, just in case... */ 217 if(err != 0) { 218 failf(data,"WSAStartup failed (%d)",err); 219 return CURLE_FAILED_INIT; 220 } 221 222 /* We have to have a WSACleanup call for every successful */ 223 /* WSAStartup call. */ 224 WSACleanup(); 225 226 /* Check that our version is supported */ 227 if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || 228 HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) { 229 /* Our version isn't supported */ 230 failf(data, "insufficient winsock version to support " 231 "telnet"); 232 return CURLE_FAILED_INIT; 233 } 234 235 /* Our version is supported */ 236 return CURLE_OK; 237 } 238 #endif 239 240 static 241 CURLcode init_telnet(struct connectdata *conn) 242 { 243 struct TELNET *tn; 244 245 tn = calloc(1, sizeof(struct TELNET)); 246 if(!tn) 247 return CURLE_OUT_OF_MEMORY; 248 249 conn->data->req.protop = tn; /* make us known */ 250 251 tn->telrcv_state = CURL_TS_DATA; 252 253 /* Init suboptions */ 254 CURL_SB_CLEAR(tn); 255 256 /* Set the options we want by default */ 257 tn->us_preferred[CURL_TELOPT_SGA] = CURL_YES; 258 tn->him_preferred[CURL_TELOPT_SGA] = CURL_YES; 259 260 /* To be compliant with previous releases of libcurl 261 we enable this option by default. This behaviour 262 can be changed thanks to the "BINARY" option in 263 CURLOPT_TELNETOPTIONS 264 */ 265 tn->us_preferred[CURL_TELOPT_BINARY] = CURL_YES; 266 tn->him_preferred[CURL_TELOPT_BINARY] = CURL_YES; 267 268 /* We must allow the server to echo what we sent 269 but it is not necessary to request the server 270 to do so (it might forces the server to close 271 the connection). Hence, we ignore ECHO in the 272 negotiate function 273 */ 274 tn->him_preferred[CURL_TELOPT_ECHO] = CURL_YES; 275 276 /* Set the subnegotiation fields to send information 277 just after negotiation passed (do/will) 278 279 Default values are (0,0) initialized by calloc. 280 According to the RFC1013 it is valid: 281 A value equal to zero is acceptable for the width (or height), 282 and means that no character width (or height) is being sent. 283 In this case, the width (or height) that will be assumed by the 284 Telnet server is operating system specific (it will probably be 285 based upon the terminal type information that may have been sent 286 using the TERMINAL TYPE Telnet option). */ 287 tn->subnegotiation[CURL_TELOPT_NAWS] = CURL_YES; 288 return CURLE_OK; 289 } 290 291 static void negotiate(struct connectdata *conn) 292 { 293 int i; 294 struct TELNET *tn = (struct TELNET *) conn->data->req.protop; 295 296 for(i = 0;i < CURL_NTELOPTS;i++) { 297 if(i==CURL_TELOPT_ECHO) 298 continue; 299 300 if(tn->us_preferred[i] == CURL_YES) 301 set_local_option(conn, i, CURL_YES); 302 303 if(tn->him_preferred[i] == CURL_YES) 304 set_remote_option(conn, i, CURL_YES); 305 } 306 } 307 308 #ifndef CURL_DISABLE_VERBOSE_STRINGS 309 static void printoption(struct Curl_easy *data, 310 const char *direction, int cmd, int option) 311 { 312 const char *fmt; 313 const char *opt; 314 315 if(data->set.verbose) { 316 if(cmd == CURL_IAC) { 317 if(CURL_TELCMD_OK(option)) 318 infof(data, "%s IAC %s\n", direction, CURL_TELCMD(option)); 319 else 320 infof(data, "%s IAC %d\n", direction, option); 321 } 322 else { 323 fmt = (cmd == CURL_WILL) ? "WILL" : (cmd == CURL_WONT) ? "WONT" : 324 (cmd == CURL_DO) ? "DO" : (cmd == CURL_DONT) ? "DONT" : 0; 325 if(fmt) { 326 if(CURL_TELOPT_OK(option)) 327 opt = CURL_TELOPT(option); 328 else if(option == CURL_TELOPT_EXOPL) 329 opt = "EXOPL"; 330 else 331 opt = NULL; 332 333 if(opt) 334 infof(data, "%s %s %s\n", direction, fmt, opt); 335 else 336 infof(data, "%s %s %d\n", direction, fmt, option); 337 } 338 else 339 infof(data, "%s %d %d\n", direction, cmd, option); 340 } 341 } 342 } 343 #endif 344 345 static void send_negotiation(struct connectdata *conn, int cmd, int option) 346 { 347 unsigned char buf[3]; 348 ssize_t bytes_written; 349 int err; 350 struct Curl_easy *data = conn->data; 351 352 buf[0] = CURL_IAC; 353 buf[1] = (unsigned char)cmd; 354 buf[2] = (unsigned char)option; 355 356 bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3); 357 if(bytes_written < 0) { 358 err = SOCKERRNO; 359 failf(data,"Sending data failed (%d)",err); 360 } 361 362 printoption(conn->data, "SENT", cmd, option); 363 } 364 365 static 366 void set_remote_option(struct connectdata *conn, int option, int newstate) 367 { 368 struct TELNET *tn = (struct TELNET *)conn->data->req.protop; 369 if(newstate == CURL_YES) { 370 switch(tn->him[option]) { 371 case CURL_NO: 372 tn->him[option] = CURL_WANTYES; 373 send_negotiation(conn, CURL_DO, option); 374 break; 375 376 case CURL_YES: 377 /* Already enabled */ 378 break; 379 380 case CURL_WANTNO: 381 switch(tn->himq[option]) { 382 case CURL_EMPTY: 383 /* Already negotiating for CURL_YES, queue the request */ 384 tn->himq[option] = CURL_OPPOSITE; 385 break; 386 case CURL_OPPOSITE: 387 /* Error: already queued an enable request */ 388 break; 389 } 390 break; 391 392 case CURL_WANTYES: 393 switch(tn->himq[option]) { 394 case CURL_EMPTY: 395 /* Error: already negotiating for enable */ 396 break; 397 case CURL_OPPOSITE: 398 tn->himq[option] = CURL_EMPTY; 399 break; 400 } 401 break; 402 } 403 } 404 else { /* NO */ 405 switch(tn->him[option]) { 406 case CURL_NO: 407 /* Already disabled */ 408 break; 409 410 case CURL_YES: 411 tn->him[option] = CURL_WANTNO; 412 send_negotiation(conn, CURL_DONT, option); 413 break; 414 415 case CURL_WANTNO: 416 switch(tn->himq[option]) { 417 case CURL_EMPTY: 418 /* Already negotiating for NO */ 419 break; 420 case CURL_OPPOSITE: 421 tn->himq[option] = CURL_EMPTY; 422 break; 423 } 424 break; 425 426 case CURL_WANTYES: 427 switch(tn->himq[option]) { 428 case CURL_EMPTY: 429 tn->himq[option] = CURL_OPPOSITE; 430 break; 431 case CURL_OPPOSITE: 432 break; 433 } 434 break; 435 } 436 } 437 } 438 439 static 440 void rec_will(struct connectdata *conn, int option) 441 { 442 struct TELNET *tn = (struct TELNET *)conn->data->req.protop; 443 switch(tn->him[option]) { 444 case CURL_NO: 445 if(tn->him_preferred[option] == CURL_YES) { 446 tn->him[option] = CURL_YES; 447 send_negotiation(conn, CURL_DO, option); 448 } 449 else 450 send_negotiation(conn, CURL_DONT, option); 451 452 break; 453 454 case CURL_YES: 455 /* Already enabled */ 456 break; 457 458 case CURL_WANTNO: 459 switch(tn->himq[option]) { 460 case CURL_EMPTY: 461 /* Error: DONT answered by WILL */ 462 tn->him[option] = CURL_NO; 463 break; 464 case CURL_OPPOSITE: 465 /* Error: DONT answered by WILL */ 466 tn->him[option] = CURL_YES; 467 tn->himq[option] = CURL_EMPTY; 468 break; 469 } 470 break; 471 472 case CURL_WANTYES: 473 switch(tn->himq[option]) { 474 case CURL_EMPTY: 475 tn->him[option] = CURL_YES; 476 break; 477 case CURL_OPPOSITE: 478 tn->him[option] = CURL_WANTNO; 479 tn->himq[option] = CURL_EMPTY; 480 send_negotiation(conn, CURL_DONT, option); 481 break; 482 } 483 break; 484 } 485 } 486 487 static 488 void rec_wont(struct connectdata *conn, int option) 489 { 490 struct TELNET *tn = (struct TELNET *)conn->data->req.protop; 491 switch(tn->him[option]) { 492 case CURL_NO: 493 /* Already disabled */ 494 break; 495 496 case CURL_YES: 497 tn->him[option] = CURL_NO; 498 send_negotiation(conn, CURL_DONT, option); 499 break; 500 501 case CURL_WANTNO: 502 switch(tn->himq[option]) { 503 case CURL_EMPTY: 504 tn->him[option] = CURL_NO; 505 break; 506 507 case CURL_OPPOSITE: 508 tn->him[option] = CURL_WANTYES; 509 tn->himq[option] = CURL_EMPTY; 510 send_negotiation(conn, CURL_DO, option); 511 break; 512 } 513 break; 514 515 case CURL_WANTYES: 516 switch(tn->himq[option]) { 517 case CURL_EMPTY: 518 tn->him[option] = CURL_NO; 519 break; 520 case CURL_OPPOSITE: 521 tn->him[option] = CURL_NO; 522 tn->himq[option] = CURL_EMPTY; 523 break; 524 } 525 break; 526 } 527 } 528 529 static void 530 set_local_option(struct connectdata *conn, int option, int newstate) 531 { 532 struct TELNET *tn = (struct TELNET *)conn->data->req.protop; 533 if(newstate == CURL_YES) { 534 switch(tn->us[option]) { 535 case CURL_NO: 536 tn->us[option] = CURL_WANTYES; 537 send_negotiation(conn, CURL_WILL, option); 538 break; 539 540 case CURL_YES: 541 /* Already enabled */ 542 break; 543 544 case CURL_WANTNO: 545 switch(tn->usq[option]) { 546 case CURL_EMPTY: 547 /* Already negotiating for CURL_YES, queue the request */ 548 tn->usq[option] = CURL_OPPOSITE; 549 break; 550 case CURL_OPPOSITE: 551 /* Error: already queued an enable request */ 552 break; 553 } 554 break; 555 556 case CURL_WANTYES: 557 switch(tn->usq[option]) { 558 case CURL_EMPTY: 559 /* Error: already negotiating for enable */ 560 break; 561 case CURL_OPPOSITE: 562 tn->usq[option] = CURL_EMPTY; 563 break; 564 } 565 break; 566 } 567 } 568 else { /* NO */ 569 switch(tn->us[option]) { 570 case CURL_NO: 571 /* Already disabled */ 572 break; 573 574 case CURL_YES: 575 tn->us[option] = CURL_WANTNO; 576 send_negotiation(conn, CURL_WONT, option); 577 break; 578 579 case CURL_WANTNO: 580 switch(tn->usq[option]) { 581 case CURL_EMPTY: 582 /* Already negotiating for NO */ 583 break; 584 case CURL_OPPOSITE: 585 tn->usq[option] = CURL_EMPTY; 586 break; 587 } 588 break; 589 590 case CURL_WANTYES: 591 switch(tn->usq[option]) { 592 case CURL_EMPTY: 593 tn->usq[option] = CURL_OPPOSITE; 594 break; 595 case CURL_OPPOSITE: 596 break; 597 } 598 break; 599 } 600 } 601 } 602 603 static 604 void rec_do(struct connectdata *conn, int option) 605 { 606 struct TELNET *tn = (struct TELNET *)conn->data->req.protop; 607 switch(tn->us[option]) { 608 case CURL_NO: 609 if(tn->us_preferred[option] == CURL_YES) { 610 tn->us[option] = CURL_YES; 611 send_negotiation(conn, CURL_WILL, option); 612 if(tn->subnegotiation[option] == CURL_YES) 613 /* transmission of data option */ 614 sendsuboption(conn, option); 615 } 616 else if(tn->subnegotiation[option] == CURL_YES) { 617 /* send information to achieve this option*/ 618 tn->us[option] = CURL_YES; 619 send_negotiation(conn, CURL_WILL, option); 620 sendsuboption(conn, option); 621 } 622 else 623 send_negotiation(conn, CURL_WONT, option); 624 break; 625 626 case CURL_YES: 627 /* Already enabled */ 628 break; 629 630 case CURL_WANTNO: 631 switch(tn->usq[option]) { 632 case CURL_EMPTY: 633 /* Error: DONT answered by WILL */ 634 tn->us[option] = CURL_NO; 635 break; 636 case CURL_OPPOSITE: 637 /* Error: DONT answered by WILL */ 638 tn->us[option] = CURL_YES; 639 tn->usq[option] = CURL_EMPTY; 640 break; 641 } 642 break; 643 644 case CURL_WANTYES: 645 switch(tn->usq[option]) { 646 case CURL_EMPTY: 647 tn->us[option] = CURL_YES; 648 if(tn->subnegotiation[option] == CURL_YES) { 649 /* transmission of data option */ 650 sendsuboption(conn, option); 651 } 652 break; 653 case CURL_OPPOSITE: 654 tn->us[option] = CURL_WANTNO; 655 tn->himq[option] = CURL_EMPTY; 656 send_negotiation(conn, CURL_WONT, option); 657 break; 658 } 659 break; 660 } 661 } 662 663 static 664 void rec_dont(struct connectdata *conn, int option) 665 { 666 struct TELNET *tn = (struct TELNET *)conn->data->req.protop; 667 switch(tn->us[option]) { 668 case CURL_NO: 669 /* Already disabled */ 670 break; 671 672 case CURL_YES: 673 tn->us[option] = CURL_NO; 674 send_negotiation(conn, CURL_WONT, option); 675 break; 676 677 case CURL_WANTNO: 678 switch(tn->usq[option]) { 679 case CURL_EMPTY: 680 tn->us[option] = CURL_NO; 681 break; 682 683 case CURL_OPPOSITE: 684 tn->us[option] = CURL_WANTYES; 685 tn->usq[option] = CURL_EMPTY; 686 send_negotiation(conn, CURL_WILL, option); 687 break; 688 } 689 break; 690 691 case CURL_WANTYES: 692 switch(tn->usq[option]) { 693 case CURL_EMPTY: 694 tn->us[option] = CURL_NO; 695 break; 696 case CURL_OPPOSITE: 697 tn->us[option] = CURL_NO; 698 tn->usq[option] = CURL_EMPTY; 699 break; 700 } 701 break; 702 } 703 } 704 705 706 static void printsub(struct Curl_easy *data, 707 int direction, /* '<' or '>' */ 708 unsigned char *pointer, /* where suboption data is */ 709 size_t length) /* length of suboption data */ 710 { 711 unsigned int i = 0; 712 713 if(data->set.verbose) { 714 if(direction) { 715 infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT"); 716 if(length >= 3) { 717 int j; 718 719 i = pointer[length-2]; 720 j = pointer[length-1]; 721 722 if(i != CURL_IAC || j != CURL_SE) { 723 infof(data, "(terminated by "); 724 if(CURL_TELOPT_OK(i)) 725 infof(data, "%s ", CURL_TELOPT(i)); 726 else if(CURL_TELCMD_OK(i)) 727 infof(data, "%s ", CURL_TELCMD(i)); 728 else 729 infof(data, "%u ", i); 730 if(CURL_TELOPT_OK(j)) 731 infof(data, "%s", CURL_TELOPT(j)); 732 else if(CURL_TELCMD_OK(j)) 733 infof(data, "%s", CURL_TELCMD(j)); 734 else 735 infof(data, "%d", j); 736 infof(data, ", not IAC SE!) "); 737 } 738 } 739 length -= 2; 740 } 741 if(length < 1) { 742 infof(data, "(Empty suboption?)"); 743 return; 744 } 745 746 if(CURL_TELOPT_OK(pointer[0])) { 747 switch(pointer[0]) { 748 case CURL_TELOPT_TTYPE: 749 case CURL_TELOPT_XDISPLOC: 750 case CURL_TELOPT_NEW_ENVIRON: 751 case CURL_TELOPT_NAWS: 752 infof(data, "%s", CURL_TELOPT(pointer[0])); 753 break; 754 default: 755 infof(data, "%s (unsupported)", CURL_TELOPT(pointer[0])); 756 break; 757 } 758 } 759 else 760 infof(data, "%d (unknown)", pointer[i]); 761 762 switch(pointer[0]) { 763 case CURL_TELOPT_NAWS: 764 if(length > 4) 765 infof(data, "Width: %hu ; Height: %hu", (pointer[1]<<8) | pointer[2], 766 (pointer[3]<<8) | pointer[4]); 767 break; 768 default: 769 switch(pointer[1]) { 770 case CURL_TELQUAL_IS: 771 infof(data, " IS"); 772 break; 773 case CURL_TELQUAL_SEND: 774 infof(data, " SEND"); 775 break; 776 case CURL_TELQUAL_INFO: 777 infof(data, " INFO/REPLY"); 778 break; 779 case CURL_TELQUAL_NAME: 780 infof(data, " NAME"); 781 break; 782 } 783 784 switch(pointer[0]) { 785 case CURL_TELOPT_TTYPE: 786 case CURL_TELOPT_XDISPLOC: 787 pointer[length] = 0; 788 infof(data, " \"%s\"", &pointer[2]); 789 break; 790 case CURL_TELOPT_NEW_ENVIRON: 791 if(pointer[1] == CURL_TELQUAL_IS) { 792 infof(data, " "); 793 for(i = 3;i < length;i++) { 794 switch(pointer[i]) { 795 case CURL_NEW_ENV_VAR: 796 infof(data, ", "); 797 break; 798 case CURL_NEW_ENV_VALUE: 799 infof(data, " = "); 800 break; 801 default: 802 infof(data, "%c", pointer[i]); 803 break; 804 } 805 } 806 } 807 break; 808 default: 809 for(i = 2; i < length; i++) 810 infof(data, " %.2x", pointer[i]); 811 break; 812 } 813 } 814 if(direction) 815 infof(data, "\n"); 816 } 817 } 818 819 static CURLcode check_telnet_options(struct connectdata *conn) 820 { 821 struct curl_slist *head; 822 struct curl_slist *beg; 823 char option_keyword[128] = ""; 824 char option_arg[256] = ""; 825 struct Curl_easy *data = conn->data; 826 struct TELNET *tn = (struct TELNET *)conn->data->req.protop; 827 CURLcode result = CURLE_OK; 828 int binary_option; 829 830 /* Add the user name as an environment variable if it 831 was given on the command line */ 832 if(conn->bits.user_passwd) { 833 snprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user); 834 beg = curl_slist_append(tn->telnet_vars, option_arg); 835 if(!beg) { 836 curl_slist_free_all(tn->telnet_vars); 837 tn->telnet_vars = NULL; 838 return CURLE_OUT_OF_MEMORY; 839 } 840 tn->telnet_vars = beg; 841 tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES; 842 } 843 844 for(head = data->set.telnet_options; head; head=head->next) { 845 if(sscanf(head->data, "%127[^= ]%*[ =]%255s", 846 option_keyword, option_arg) == 2) { 847 848 /* Terminal type */ 849 if(Curl_raw_equal(option_keyword, "TTYPE")) { 850 strncpy(tn->subopt_ttype, option_arg, 31); 851 tn->subopt_ttype[31] = 0; /* String termination */ 852 tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES; 853 continue; 854 } 855 856 /* Display variable */ 857 if(Curl_raw_equal(option_keyword, "XDISPLOC")) { 858 strncpy(tn->subopt_xdisploc, option_arg, 127); 859 tn->subopt_xdisploc[127] = 0; /* String termination */ 860 tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES; 861 continue; 862 } 863 864 /* Environment variable */ 865 if(Curl_raw_equal(option_keyword, "NEW_ENV")) { 866 beg = curl_slist_append(tn->telnet_vars, option_arg); 867 if(!beg) { 868 result = CURLE_OUT_OF_MEMORY; 869 break; 870 } 871 tn->telnet_vars = beg; 872 tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES; 873 continue; 874 } 875 876 /* Window Size */ 877 if(Curl_raw_equal(option_keyword, "WS")) { 878 if(sscanf(option_arg, "%hu%*[xX]%hu", 879 &tn->subopt_wsx, &tn->subopt_wsy) == 2) 880 tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES; 881 else { 882 failf(data, "Syntax error in telnet option: %s", head->data); 883 result = CURLE_TELNET_OPTION_SYNTAX; 884 break; 885 } 886 continue; 887 } 888 889 /* To take care or not of the 8th bit in data exchange */ 890 if(Curl_raw_equal(option_keyword, "BINARY")) { 891 binary_option=atoi(option_arg); 892 if(binary_option!=1) { 893 tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO; 894 tn->him_preferred[CURL_TELOPT_BINARY] = CURL_NO; 895 } 896 continue; 897 } 898 899 failf(data, "Unknown telnet option %s", head->data); 900 result = CURLE_UNKNOWN_TELNET_OPTION; 901 break; 902 } 903 else { 904 failf(data, "Syntax error in telnet option: %s", head->data); 905 result = CURLE_TELNET_OPTION_SYNTAX; 906 break; 907 } 908 } 909 910 if(result) { 911 curl_slist_free_all(tn->telnet_vars); 912 tn->telnet_vars = NULL; 913 } 914 915 return result; 916 } 917 918 /* 919 * suboption() 920 * 921 * Look at the sub-option buffer, and try to be helpful to the other 922 * side. 923 */ 924 925 static void suboption(struct connectdata *conn) 926 { 927 struct curl_slist *v; 928 unsigned char temp[2048]; 929 ssize_t bytes_written; 930 size_t len; 931 size_t tmplen; 932 int err; 933 char varname[128] = ""; 934 char varval[128] = ""; 935 struct Curl_easy *data = conn->data; 936 struct TELNET *tn = (struct TELNET *)data->req.protop; 937 938 printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2); 939 switch (CURL_SB_GET(tn)) { 940 case CURL_TELOPT_TTYPE: 941 len = strlen(tn->subopt_ttype) + 4 + 2; 942 snprintf((char *)temp, sizeof(temp), 943 "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE, 944 CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE); 945 bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); 946 if(bytes_written < 0) { 947 err = SOCKERRNO; 948 failf(data,"Sending data failed (%d)",err); 949 } 950 printsub(data, '>', &temp[2], len-2); 951 break; 952 case CURL_TELOPT_XDISPLOC: 953 len = strlen(tn->subopt_xdisploc) + 4 + 2; 954 snprintf((char *)temp, sizeof(temp), 955 "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC, 956 CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE); 957 bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); 958 if(bytes_written < 0) { 959 err = SOCKERRNO; 960 failf(data,"Sending data failed (%d)",err); 961 } 962 printsub(data, '>', &temp[2], len-2); 963 break; 964 case CURL_TELOPT_NEW_ENVIRON: 965 snprintf((char *)temp, sizeof(temp), 966 "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON, 967 CURL_TELQUAL_IS); 968 len = 4; 969 970 for(v = tn->telnet_vars;v;v = v->next) { 971 tmplen = (strlen(v->data) + 1); 972 /* Add the variable only if it fits */ 973 if(len + tmplen < (int)sizeof(temp)-6) { 974 if(sscanf(v->data, "%127[^,],%127s", varname, varval)) { 975 snprintf((char *)&temp[len], sizeof(temp) - len, 976 "%c%s%c%s", CURL_NEW_ENV_VAR, varname, 977 CURL_NEW_ENV_VALUE, varval); 978 len += tmplen; 979 } 980 } 981 } 982 snprintf((char *)&temp[len], sizeof(temp) - len, 983 "%c%c", CURL_IAC, CURL_SE); 984 len += 2; 985 bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); 986 if(bytes_written < 0) { 987 err = SOCKERRNO; 988 failf(data,"Sending data failed (%d)",err); 989 } 990 printsub(data, '>', &temp[2], len-2); 991 break; 992 } 993 return; 994 } 995 996 997 /* 998 * sendsuboption() 999 * 1000 * Send suboption information to the server side. 1001 */ 1002 1003 static void sendsuboption(struct connectdata *conn, int option) 1004 { 1005 ssize_t bytes_written; 1006 int err; 1007 unsigned short x, y; 1008 unsigned char*uc1, *uc2; 1009 1010 struct Curl_easy *data = conn->data; 1011 struct TELNET *tn = (struct TELNET *)data->req.protop; 1012 1013 switch (option) { 1014 case CURL_TELOPT_NAWS: 1015 /* We prepare data to be sent */ 1016 CURL_SB_CLEAR(tn); 1017 CURL_SB_ACCUM(tn, CURL_IAC); 1018 CURL_SB_ACCUM(tn, CURL_SB); 1019 CURL_SB_ACCUM(tn, CURL_TELOPT_NAWS); 1020 /* We must deal either with litte or big endien processors */ 1021 /* Window size must be sent according to the 'network order' */ 1022 x=htons(tn->subopt_wsx); 1023 y=htons(tn->subopt_wsy); 1024 uc1 = (unsigned char*)&x; 1025 uc2 = (unsigned char*)&y; 1026 CURL_SB_ACCUM(tn, uc1[0]); 1027 CURL_SB_ACCUM(tn, uc1[1]); 1028 CURL_SB_ACCUM(tn, uc2[0]); 1029 CURL_SB_ACCUM(tn, uc2[1]); 1030 1031 CURL_SB_ACCUM(tn, CURL_IAC); 1032 CURL_SB_ACCUM(tn, CURL_SE); 1033 CURL_SB_TERM(tn); 1034 /* data suboption is now ready */ 1035 1036 printsub(data, '>', (unsigned char *)tn->subbuffer+2, 1037 CURL_SB_LEN(tn)-2); 1038 1039 /* we send the header of the suboption... */ 1040 bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer, 3); 1041 if(bytes_written < 0) { 1042 err = SOCKERRNO; 1043 failf(data, "Sending data failed (%d)", err); 1044 } 1045 /* ... then the window size with the send_telnet_data() function 1046 to deal with 0xFF cases ... */ 1047 send_telnet_data(conn, (char *)tn->subbuffer+3, 4); 1048 /* ... and the footer */ 1049 bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer+7, 2); 1050 if(bytes_written < 0) { 1051 err = SOCKERRNO; 1052 failf(data, "Sending data failed (%d)", err); 1053 } 1054 break; 1055 } 1056 } 1057 1058 1059 static 1060 CURLcode telrcv(struct connectdata *conn, 1061 const unsigned char *inbuf, /* Data received from socket */ 1062 ssize_t count) /* Number of bytes received */ 1063 { 1064 unsigned char c; 1065 CURLcode result; 1066 int in = 0; 1067 int startwrite=-1; 1068 struct Curl_easy *data = conn->data; 1069 struct TELNET *tn = (struct TELNET *)data->req.protop; 1070 1071 #define startskipping() \ 1072 if(startwrite >= 0) { \ 1073 result = Curl_client_write(conn, \ 1074 CLIENTWRITE_BODY, \ 1075 (char *)&inbuf[startwrite], \ 1076 in-startwrite); \ 1077 if(result) \ 1078 return result; \ 1079 } \ 1080 startwrite = -1 1081 1082 #define writebyte() \ 1083 if(startwrite < 0) \ 1084 startwrite = in 1085 1086 #define bufferflush() startskipping() 1087 1088 while(count--) { 1089 c = inbuf[in]; 1090 1091 switch (tn->telrcv_state) { 1092 case CURL_TS_CR: 1093 tn->telrcv_state = CURL_TS_DATA; 1094 if(c == '\0') { 1095 startskipping(); 1096 break; /* Ignore \0 after CR */ 1097 } 1098 writebyte(); 1099 break; 1100 1101 case CURL_TS_DATA: 1102 if(c == CURL_IAC) { 1103 tn->telrcv_state = CURL_TS_IAC; 1104 startskipping(); 1105 break; 1106 } 1107 else if(c == '\r') 1108 tn->telrcv_state = CURL_TS_CR; 1109 writebyte(); 1110 break; 1111 1112 case CURL_TS_IAC: 1113 process_iac: 1114 DEBUGASSERT(startwrite < 0); 1115 switch (c) { 1116 case CURL_WILL: 1117 tn->telrcv_state = CURL_TS_WILL; 1118 break; 1119 case CURL_WONT: 1120 tn->telrcv_state = CURL_TS_WONT; 1121 break; 1122 case CURL_DO: 1123 tn->telrcv_state = CURL_TS_DO; 1124 break; 1125 case CURL_DONT: 1126 tn->telrcv_state = CURL_TS_DONT; 1127 break; 1128 case CURL_SB: 1129 CURL_SB_CLEAR(tn); 1130 tn->telrcv_state = CURL_TS_SB; 1131 break; 1132 case CURL_IAC: 1133 tn->telrcv_state = CURL_TS_DATA; 1134 writebyte(); 1135 break; 1136 case CURL_DM: 1137 case CURL_NOP: 1138 case CURL_GA: 1139 default: 1140 tn->telrcv_state = CURL_TS_DATA; 1141 printoption(data, "RCVD", CURL_IAC, c); 1142 break; 1143 } 1144 break; 1145 1146 case CURL_TS_WILL: 1147 printoption(data, "RCVD", CURL_WILL, c); 1148 tn->please_negotiate = 1; 1149 rec_will(conn, c); 1150 tn->telrcv_state = CURL_TS_DATA; 1151 break; 1152 1153 case CURL_TS_WONT: 1154 printoption(data, "RCVD", CURL_WONT, c); 1155 tn->please_negotiate = 1; 1156 rec_wont(conn, c); 1157 tn->telrcv_state = CURL_TS_DATA; 1158 break; 1159 1160 case CURL_TS_DO: 1161 printoption(data, "RCVD", CURL_DO, c); 1162 tn->please_negotiate = 1; 1163 rec_do(conn, c); 1164 tn->telrcv_state = CURL_TS_DATA; 1165 break; 1166 1167 case CURL_TS_DONT: 1168 printoption(data, "RCVD", CURL_DONT, c); 1169 tn->please_negotiate = 1; 1170 rec_dont(conn, c); 1171 tn->telrcv_state = CURL_TS_DATA; 1172 break; 1173 1174 case CURL_TS_SB: 1175 if(c == CURL_IAC) 1176 tn->telrcv_state = CURL_TS_SE; 1177 else 1178 CURL_SB_ACCUM(tn, c); 1179 break; 1180 1181 case CURL_TS_SE: 1182 if(c != CURL_SE) { 1183 if(c != CURL_IAC) { 1184 /* 1185 * This is an error. We only expect to get "IAC IAC" or "IAC SE". 1186 * Several things may have happened. An IAC was not doubled, the 1187 * IAC SE was left off, or another option got inserted into the 1188 * suboption are all possibilities. If we assume that the IAC was 1189 * not doubled, and really the IAC SE was left off, we could get 1190 * into an infinate loop here. So, instead, we terminate the 1191 * suboption, and process the partial suboption if we can. 1192 */ 1193 CURL_SB_ACCUM(tn, CURL_IAC); 1194 CURL_SB_ACCUM(tn, c); 1195 tn->subpointer -= 2; 1196 CURL_SB_TERM(tn); 1197 1198 printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c); 1199 suboption(conn); /* handle sub-option */ 1200 tn->telrcv_state = CURL_TS_IAC; 1201 goto process_iac; 1202 } 1203 CURL_SB_ACCUM(tn, c); 1204 tn->telrcv_state = CURL_TS_SB; 1205 } 1206 else 1207 { 1208 CURL_SB_ACCUM(tn, CURL_IAC); 1209 CURL_SB_ACCUM(tn, CURL_SE); 1210 tn->subpointer -= 2; 1211 CURL_SB_TERM(tn); 1212 suboption(conn); /* handle sub-option */ 1213 tn->telrcv_state = CURL_TS_DATA; 1214 } 1215 break; 1216 } 1217 ++in; 1218 } 1219 bufferflush(); 1220 return CURLE_OK; 1221 } 1222 1223 /* Escape and send a telnet data block */ 1224 /* TODO: write large chunks of data instead of one byte at a time */ 1225 static CURLcode send_telnet_data(struct connectdata *conn, 1226 char *buffer, ssize_t nread) 1227 { 1228 unsigned char outbuf[2]; 1229 ssize_t bytes_written, total_written; 1230 int out_count; 1231 CURLcode result = CURLE_OK; 1232 1233 while(!result && nread--) { 1234 outbuf[0] = *buffer++; 1235 out_count = 1; 1236 if(outbuf[0] == CURL_IAC) 1237 outbuf[out_count++] = CURL_IAC; 1238 1239 total_written = 0; 1240 do { 1241 /* Make sure socket is writable to avoid EWOULDBLOCK condition */ 1242 struct pollfd pfd[1]; 1243 pfd[0].fd = conn->sock[FIRSTSOCKET]; 1244 pfd[0].events = POLLOUT; 1245 switch (Curl_poll(pfd, 1, -1)) { 1246 case -1: /* error, abort writing */ 1247 case 0: /* timeout (will never happen) */ 1248 result = CURLE_SEND_ERROR; 1249 break; 1250 default: /* write! */ 1251 bytes_written = 0; 1252 result = Curl_write(conn, conn->sock[FIRSTSOCKET], 1253 outbuf+total_written, out_count-total_written, 1254 &bytes_written); 1255 total_written += bytes_written; 1256 break; 1257 } 1258 /* handle partial write */ 1259 } while(!result && total_written < out_count); 1260 } 1261 return result; 1262 } 1263 1264 static CURLcode telnet_done(struct connectdata *conn, 1265 CURLcode status, bool premature) 1266 { 1267 struct TELNET *tn = (struct TELNET *)conn->data->req.protop; 1268 (void)status; /* unused */ 1269 (void)premature; /* not used */ 1270 1271 if(!tn) 1272 return CURLE_OK; 1273 1274 curl_slist_free_all(tn->telnet_vars); 1275 tn->telnet_vars = NULL; 1276 1277 Curl_safefree(conn->data->req.protop); 1278 1279 return CURLE_OK; 1280 } 1281 1282 static CURLcode telnet_do(struct connectdata *conn, bool *done) 1283 { 1284 CURLcode result; 1285 struct Curl_easy *data = conn->data; 1286 curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; 1287 #ifdef USE_WINSOCK 1288 HMODULE wsock2; 1289 WSOCK2_FUNC close_event_func; 1290 WSOCK2_FUNC create_event_func; 1291 WSOCK2_FUNC event_select_func; 1292 WSOCK2_FUNC enum_netevents_func; 1293 WSAEVENT event_handle; 1294 WSANETWORKEVENTS events; 1295 HANDLE stdin_handle; 1296 HANDLE objs[2]; 1297 DWORD obj_count; 1298 DWORD wait_timeout; 1299 DWORD waitret; 1300 DWORD readfile_read; 1301 int err; 1302 #else 1303 int interval_ms; 1304 struct pollfd pfd[2]; 1305 int poll_cnt; 1306 curl_off_t total_dl = 0; 1307 curl_off_t total_ul = 0; 1308 #endif 1309 ssize_t nread; 1310 struct timeval now; 1311 bool keepon = TRUE; 1312 char *buf = data->state.buffer; 1313 struct TELNET *tn; 1314 1315 *done = TRUE; /* unconditionally */ 1316 1317 result = init_telnet(conn); 1318 if(result) 1319 return result; 1320 1321 tn = (struct TELNET *)data->req.protop; 1322 1323 result = check_telnet_options(conn); 1324 if(result) 1325 return result; 1326 1327 #ifdef USE_WINSOCK 1328 /* 1329 ** This functionality only works with WinSock >= 2.0. So, 1330 ** make sure have it. 1331 */ 1332 result = check_wsock2(data); 1333 if(result) 1334 return result; 1335 1336 /* OK, so we have WinSock 2.0. We need to dynamically */ 1337 /* load ws2_32.dll and get the function pointers we need. */ 1338 wsock2 = Curl_load_library(TEXT("WS2_32.DLL")); 1339 if(wsock2 == NULL) { 1340 failf(data, "failed to load WS2_32.DLL (%d)", ERRNO); 1341 return CURLE_FAILED_INIT; 1342 } 1343 1344 /* Grab a pointer to WSACreateEvent */ 1345 create_event_func = GetProcAddress(wsock2, "WSACreateEvent"); 1346 if(create_event_func == NULL) { 1347 failf(data, "failed to find WSACreateEvent function (%d)", ERRNO); 1348 FreeLibrary(wsock2); 1349 return CURLE_FAILED_INIT; 1350 } 1351 1352 /* And WSACloseEvent */ 1353 close_event_func = GetProcAddress(wsock2, "WSACloseEvent"); 1354 if(close_event_func == NULL) { 1355 failf(data, "failed to find WSACloseEvent function (%d)", ERRNO); 1356 FreeLibrary(wsock2); 1357 return CURLE_FAILED_INIT; 1358 } 1359 1360 /* And WSAEventSelect */ 1361 event_select_func = GetProcAddress(wsock2, "WSAEventSelect"); 1362 if(event_select_func == NULL) { 1363 failf(data, "failed to find WSAEventSelect function (%d)", ERRNO); 1364 FreeLibrary(wsock2); 1365 return CURLE_FAILED_INIT; 1366 } 1367 1368 /* And WSAEnumNetworkEvents */ 1369 enum_netevents_func = GetProcAddress(wsock2, "WSAEnumNetworkEvents"); 1370 if(enum_netevents_func == NULL) { 1371 failf(data, "failed to find WSAEnumNetworkEvents function (%d)", ERRNO); 1372 FreeLibrary(wsock2); 1373 return CURLE_FAILED_INIT; 1374 } 1375 1376 /* We want to wait for both stdin and the socket. Since 1377 ** the select() function in winsock only works on sockets 1378 ** we have to use the WaitForMultipleObjects() call. 1379 */ 1380 1381 /* First, create a sockets event object */ 1382 event_handle = (WSAEVENT)create_event_func(); 1383 if(event_handle == WSA_INVALID_EVENT) { 1384 failf(data, "WSACreateEvent failed (%d)", SOCKERRNO); 1385 FreeLibrary(wsock2); 1386 return CURLE_FAILED_INIT; 1387 } 1388 1389 /* Tell winsock what events we want to listen to */ 1390 if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) == 1391 SOCKET_ERROR) { 1392 close_event_func(event_handle); 1393 FreeLibrary(wsock2); 1394 return CURLE_OK; 1395 } 1396 1397 /* The get the Windows file handle for stdin */ 1398 stdin_handle = GetStdHandle(STD_INPUT_HANDLE); 1399 1400 /* Create the list of objects to wait for */ 1401 objs[0] = event_handle; 1402 objs[1] = stdin_handle; 1403 1404 /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it, 1405 else use the old WaitForMultipleObjects() way */ 1406 if(GetFileType(stdin_handle) == FILE_TYPE_PIPE || 1407 data->set.is_fread_set) { 1408 /* Don't wait for stdin_handle, just wait for event_handle */ 1409 obj_count = 1; 1410 /* Check stdin_handle per 100 milliseconds */ 1411 wait_timeout = 100; 1412 } 1413 else { 1414 obj_count = 2; 1415 wait_timeout = 1000; 1416 } 1417 1418 /* Keep on listening and act on events */ 1419 while(keepon) { 1420 waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout); 1421 switch(waitret) { 1422 case WAIT_TIMEOUT: 1423 { 1424 for(;;) { 1425 if(data->set.is_fread_set) { 1426 /* read from user-supplied method */ 1427 result = (int)data->state.fread_func(buf, 1, BUFSIZE - 1, 1428 data->state.in); 1429 if(result == CURL_READFUNC_ABORT) { 1430 keepon = FALSE; 1431 result = CURLE_READ_ERROR; 1432 break; 1433 } 1434 1435 if(result == CURL_READFUNC_PAUSE) 1436 break; 1437 1438 if(result == 0) /* no bytes */ 1439 break; 1440 1441 readfile_read = result; /* fall thru with number of bytes read */ 1442 } 1443 else { 1444 /* read from stdin */ 1445 if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, 1446 &readfile_read, NULL)) { 1447 keepon = FALSE; 1448 result = CURLE_READ_ERROR; 1449 break; 1450 } 1451 1452 if(!readfile_read) 1453 break; 1454 1455 if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer), 1456 &readfile_read, NULL)) { 1457 keepon = FALSE; 1458 result = CURLE_READ_ERROR; 1459 break; 1460 } 1461 } 1462 1463 result = send_telnet_data(conn, buf, readfile_read); 1464 if(result) { 1465 keepon = FALSE; 1466 break; 1467 } 1468 } 1469 } 1470 break; 1471 1472 case WAIT_OBJECT_0 + 1: 1473 { 1474 if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer), 1475 &readfile_read, NULL)) { 1476 keepon = FALSE; 1477 result = CURLE_READ_ERROR; 1478 break; 1479 } 1480 1481 result = send_telnet_data(conn, buf, readfile_read); 1482 if(result) { 1483 keepon = FALSE; 1484 break; 1485 } 1486 } 1487 break; 1488 1489 case WAIT_OBJECT_0: 1490 1491 events.lNetworkEvents = 0; 1492 if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) { 1493 if((err = SOCKERRNO) != EINPROGRESS) { 1494 infof(data, "WSAEnumNetworkEvents failed (%d)", err); 1495 keepon = FALSE; 1496 result = CURLE_READ_ERROR; 1497 } 1498 break; 1499 } 1500 if(events.lNetworkEvents & FD_READ) { 1501 /* read data from network */ 1502 result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); 1503 /* read would've blocked. Loop again */ 1504 if(result == CURLE_AGAIN) 1505 break; 1506 /* returned not-zero, this an error */ 1507 else if(result) { 1508 keepon = FALSE; 1509 break; 1510 } 1511 /* returned zero but actually received 0 or less here, 1512 the server closed the connection and we bail out */ 1513 else if(nread <= 0) { 1514 keepon = FALSE; 1515 break; 1516 } 1517 1518 result = telrcv(conn, (unsigned char *) buf, nread); 1519 if(result) { 1520 keepon = FALSE; 1521 break; 1522 } 1523 1524 /* Negotiate if the peer has started negotiating, 1525 otherwise don't. We don't want to speak telnet with 1526 non-telnet servers, like POP or SMTP. */ 1527 if(tn->please_negotiate && !tn->already_negotiated) { 1528 negotiate(conn); 1529 tn->already_negotiated = 1; 1530 } 1531 } 1532 if(events.lNetworkEvents & FD_CLOSE) { 1533 keepon = FALSE; 1534 } 1535 break; 1536 1537 } 1538 1539 if(data->set.timeout) { 1540 now = Curl_tvnow(); 1541 if(Curl_tvdiff(now, conn->created) >= data->set.timeout) { 1542 failf(data, "Time-out"); 1543 result = CURLE_OPERATION_TIMEDOUT; 1544 keepon = FALSE; 1545 } 1546 } 1547 } 1548 1549 /* We called WSACreateEvent, so call WSACloseEvent */ 1550 if(!close_event_func(event_handle)) { 1551 infof(data, "WSACloseEvent failed (%d)", SOCKERRNO); 1552 } 1553 1554 /* "Forget" pointers into the library we're about to free */ 1555 create_event_func = NULL; 1556 close_event_func = NULL; 1557 event_select_func = NULL; 1558 enum_netevents_func = NULL; 1559 1560 /* We called LoadLibrary, so call FreeLibrary */ 1561 if(!FreeLibrary(wsock2)) 1562 infof(data, "FreeLibrary(wsock2) failed (%d)", ERRNO); 1563 #else 1564 pfd[0].fd = sockfd; 1565 pfd[0].events = POLLIN; 1566 1567 if(data->set.is_fread_set) { 1568 poll_cnt = 1; 1569 interval_ms = 100; /* poll user-supplied read function */ 1570 } 1571 else { 1572 /* really using fread, so infile is a FILE* */ 1573 pfd[1].fd = fileno((FILE *)data->state.in); 1574 pfd[1].events = POLLIN; 1575 poll_cnt = 2; 1576 interval_ms = 1 * 1000; 1577 } 1578 1579 while(keepon) { 1580 switch (Curl_poll(pfd, poll_cnt, interval_ms)) { 1581 case -1: /* error, stop reading */ 1582 keepon = FALSE; 1583 continue; 1584 case 0: /* timeout */ 1585 pfd[0].revents = 0; 1586 pfd[1].revents = 0; 1587 /* fall through */ 1588 default: /* read! */ 1589 if(pfd[0].revents & POLLIN) { 1590 /* read data from network */ 1591 result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); 1592 /* read would've blocked. Loop again */ 1593 if(result == CURLE_AGAIN) 1594 break; 1595 /* returned not-zero, this an error */ 1596 else if(result) { 1597 keepon = FALSE; 1598 break; 1599 } 1600 /* returned zero but actually received 0 or less here, 1601 the server closed the connection and we bail out */ 1602 else if(nread <= 0) { 1603 keepon = FALSE; 1604 break; 1605 } 1606 1607 total_dl += nread; 1608 Curl_pgrsSetDownloadCounter(data, total_dl); 1609 result = telrcv(conn, (unsigned char *)buf, nread); 1610 if(result) { 1611 keepon = FALSE; 1612 break; 1613 } 1614 1615 /* Negotiate if the peer has started negotiating, 1616 otherwise don't. We don't want to speak telnet with 1617 non-telnet servers, like POP or SMTP. */ 1618 if(tn->please_negotiate && !tn->already_negotiated) { 1619 negotiate(conn); 1620 tn->already_negotiated = 1; 1621 } 1622 } 1623 1624 nread = 0; 1625 if(poll_cnt == 2) { 1626 if(pfd[1].revents & POLLIN) { /* read from in file */ 1627 nread = read(pfd[1].fd, buf, BUFSIZE - 1); 1628 } 1629 } 1630 else { 1631 /* read from user-supplied method */ 1632 nread = (int)data->state.fread_func(buf, 1, BUFSIZE - 1, 1633 data->state.in); 1634 if(nread == CURL_READFUNC_ABORT) { 1635 keepon = FALSE; 1636 break; 1637 } 1638 if(nread == CURL_READFUNC_PAUSE) 1639 break; 1640 } 1641 1642 if(nread > 0) { 1643 result = send_telnet_data(conn, buf, nread); 1644 if(result) { 1645 keepon = FALSE; 1646 break; 1647 } 1648 total_ul += nread; 1649 Curl_pgrsSetUploadCounter(data, total_ul); 1650 } 1651 else if(nread < 0) 1652 keepon = FALSE; 1653 1654 break; 1655 } /* poll switch statement */ 1656 1657 if(data->set.timeout) { 1658 now = Curl_tvnow(); 1659 if(Curl_tvdiff(now, conn->created) >= data->set.timeout) { 1660 failf(data, "Time-out"); 1661 result = CURLE_OPERATION_TIMEDOUT; 1662 keepon = FALSE; 1663 } 1664 } 1665 1666 if(Curl_pgrsUpdate(conn)) { 1667 result = CURLE_ABORTED_BY_CALLBACK; 1668 break; 1669 } 1670 } 1671 #endif 1672 /* mark this as "no further transfer wanted" */ 1673 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); 1674 1675 return result; 1676 } 1677 #endif 1678