telnet.c 40 KB

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