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