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