telnet.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <winsock.h>
  5. #include "putty.h"
  6. #ifndef FALSE
  7. #define FALSE 0
  8. #endif
  9. #ifndef TRUE
  10. #define TRUE 1
  11. #endif
  12. static SOCKET s = INVALID_SOCKET;
  13. #define IAC 255 /* interpret as command: */
  14. #define DONT 254 /* you are not to use option */
  15. #define DO 253 /* please, you use option */
  16. #define WONT 252 /* I won't use option */
  17. #define WILL 251 /* I will use option */
  18. #define SB 250 /* interpret as subnegotiation */
  19. #define SE 240 /* end sub negotiation */
  20. #define GA 249 /* you may reverse the line */
  21. #define EL 248 /* erase the current line */
  22. #define EC 247 /* erase the current character */
  23. #define AYT 246 /* are you there */
  24. #define AO 245 /* abort output--but let prog finish */
  25. #define IP 244 /* interrupt process--permanently */
  26. #define BREAK 243 /* break */
  27. #define DM 242 /* data mark--for connect. cleaning */
  28. #define NOP 241 /* nop */
  29. #define EOR 239 /* end of record (transparent mode) */
  30. #define ABORT 238 /* Abort process */
  31. #define SUSP 237 /* Suspend process */
  32. #define xEOF 236 /* End of file: EOF is already used... */
  33. #define TELOPT_BINARY 0 /* 8-bit data path */
  34. #define TELOPT_ECHO 1 /* echo */
  35. #define TELOPT_RCP 2 /* prepare to reconnect */
  36. #define TELOPT_SGA 3 /* suppress go ahead */
  37. #define TELOPT_NAMS 4 /* approximate message size */
  38. #define TELOPT_STATUS 5 /* give status */
  39. #define TELOPT_TM 6 /* timing mark */
  40. #define TELOPT_RCTE 7 /* remote controlled transmission and echo */
  41. #define TELOPT_NAOL 8 /* negotiate about output line width */
  42. #define TELOPT_NAOP 9 /* negotiate about output page size */
  43. #define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
  44. #define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
  45. #define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
  46. #define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
  47. #define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
  48. #define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
  49. #define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
  50. #define TELOPT_XASCII 17 /* extended ascic character set */
  51. #define TELOPT_LOGOUT 18 /* force logout */
  52. #define TELOPT_BM 19 /* byte macro */
  53. #define TELOPT_DET 20 /* data entry terminal */
  54. #define TELOPT_SUPDUP 21 /* supdup protocol */
  55. #define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
  56. #define TELOPT_SNDLOC 23 /* send location */
  57. #define TELOPT_TTYPE 24 /* terminal type */
  58. #define TELOPT_EOR 25 /* end or record */
  59. #define TELOPT_TUID 26 /* TACACS user identification */
  60. #define TELOPT_OUTMRK 27 /* output marking */
  61. #define TELOPT_TTYLOC 28 /* terminal location number */
  62. #define TELOPT_3270REGIME 29 /* 3270 regime */
  63. #define TELOPT_X3PAD 30 /* X.3 PAD */
  64. #define TELOPT_NAWS 31 /* window size */
  65. #define TELOPT_TSPEED 32 /* terminal speed */
  66. #define TELOPT_LFLOW 33 /* remote flow control */
  67. #define TELOPT_LINEMODE 34 /* Linemode option */
  68. #define TELOPT_XDISPLOC 35 /* X Display Location */
  69. #define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */
  70. #define TELOPT_AUTHENTICATION 37/* Authenticate */
  71. #define TELOPT_ENCRYPT 38 /* Encryption option */
  72. #define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */
  73. #define TELOPT_EXOPL 255 /* extended-options-list */
  74. #define TELQUAL_IS 0 /* option is... */
  75. #define TELQUAL_SEND 1 /* send option */
  76. #define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */
  77. #define BSD_VAR 1
  78. #define BSD_VALUE 0
  79. #define RFC_VAR 0
  80. #define RFC_VALUE 1
  81. #define CR 13
  82. #define LF 10
  83. #define NUL 0
  84. #define iswritable(x) ( (x) != IAC && (x) != CR )
  85. static char *telopt(int opt) {
  86. #define i(x) if (opt == TELOPT_ ## x) return #x;
  87. i(BINARY); i(ECHO); i(RCP); i(SGA); i(NAMS); i(STATUS); i(TM); i(RCTE);
  88. i(NAOL); i(NAOP); i(NAOCRD); i(NAOHTS); i(NAOHTD); i(NAOFFD); i(NAOVTS);
  89. i(NAOVTD); i(NAOLFD); i(XASCII); i(LOGOUT); i(BM); i(DET); i(SUPDUP);
  90. i(SUPDUPOUTPUT); i(SNDLOC); i(TTYPE); i(EOR); i(TUID); i(OUTMRK);
  91. i(TTYLOC); i(X3PAD); i(NAWS); i(TSPEED); i(LFLOW); i(LINEMODE);
  92. i(XDISPLOC); i(OLD_ENVIRON); i(AUTHENTICATION); i(ENCRYPT);
  93. i(NEW_ENVIRON); i(EXOPL);
  94. #undef i
  95. return "<unknown>";
  96. }
  97. static void telnet_size(void);
  98. struct Opt {
  99. int send; /* what we initially send */
  100. int nsend; /* -ve send if requested to stop it */
  101. int ack, nak; /* +ve and -ve acknowledgements */
  102. int option; /* the option code */
  103. enum {
  104. REQUESTED, ACTIVE, INACTIVE, REALLY_INACTIVE
  105. } state;
  106. };
  107. static struct Opt o_naws = {WILL, WONT, DO, DONT, TELOPT_NAWS, REQUESTED};
  108. static struct Opt o_tspeed = {WILL, WONT, DO, DONT, TELOPT_TSPEED, REQUESTED};
  109. static struct Opt o_ttype = {WILL, WONT, DO, DONT, TELOPT_TTYPE, REQUESTED};
  110. static struct Opt o_oenv = {WILL, WONT, DO, DONT, TELOPT_OLD_ENVIRON,
  111. INACTIVE};
  112. static struct Opt o_nenv = {WILL, WONT, DO, DONT, TELOPT_NEW_ENVIRON,
  113. REQUESTED};
  114. static struct Opt o_echo = {DO, DONT, WILL, WONT, TELOPT_ECHO, REQUESTED};
  115. static struct Opt o_we_sga = {WILL, WONT, DO, DONT, TELOPT_SGA, REQUESTED};
  116. static struct Opt o_they_sga = {DO, DONT, WILL, WONT, TELOPT_SGA, REQUESTED};
  117. static struct Opt *opts[] = {
  118. &o_naws, &o_tspeed, &o_ttype, &o_oenv, &o_nenv, &o_echo,
  119. &o_we_sga, &o_they_sga, NULL
  120. };
  121. static int in_synch;
  122. static int sb_opt, sb_len;
  123. static char *sb_buf = NULL;
  124. static int sb_size = 0;
  125. #define SB_DELTA 1024
  126. static void try_write (void) {
  127. while (outbuf_head != outbuf_reap) {
  128. int end = (outbuf_reap < outbuf_head ? outbuf_head : OUTBUF_SIZE);
  129. int len = end - outbuf_reap;
  130. int ret;
  131. ret = send (s, outbuf+outbuf_reap, len, 0);
  132. if (ret > 0)
  133. outbuf_reap = (outbuf_reap + ret) & OUTBUF_MASK;
  134. if (ret < len)
  135. return;
  136. }
  137. }
  138. static void s_write (void *buf, int len) {
  139. unsigned char *p = buf;
  140. while (len--) {
  141. int new_head = (outbuf_head + 1) & OUTBUF_MASK;
  142. if (new_head != outbuf_reap) {
  143. outbuf[outbuf_head] = *p++;
  144. outbuf_head = new_head;
  145. }
  146. }
  147. try_write();
  148. }
  149. static void c_write (char *buf, int len) {
  150. while (len--) {
  151. int new_head = (inbuf_head + 1) & INBUF_MASK;
  152. if (new_head != inbuf_reap) {
  153. inbuf[inbuf_head] = *buf++;
  154. inbuf_head = new_head;
  155. } else {
  156. term_out();
  157. if( inbuf_head == inbuf_reap ) len++; else break;
  158. }
  159. }
  160. }
  161. static void log_option (char *sender, int cmd, int option) {
  162. char buf[50];
  163. sprintf(buf, "%s:\t%s %s", sender,
  164. (cmd == WILL ? "WILL" : cmd == WONT ? "WONT" :
  165. cmd == DO ? "DO" : cmd == DONT ? "DONT" : "<??>"),
  166. telopt(option));
  167. logevent(buf);
  168. }
  169. static void send_opt (int cmd, int option) {
  170. unsigned char b[3];
  171. b[0] = IAC; b[1] = cmd; b[2] = option;
  172. s_write (b, 3);
  173. log_option("client", cmd, option);
  174. }
  175. static void deactivate_option (struct Opt *o) {
  176. if (o->state == REQUESTED || o->state == ACTIVE)
  177. send_opt (o->nsend, o->option);
  178. o->state = REALLY_INACTIVE;
  179. }
  180. static void activate_option (struct Opt *o) {
  181. if (o->send == WILL && o->option == TELOPT_NAWS)
  182. telnet_size();
  183. if (o->send == WILL &&
  184. (o->option == TELOPT_NEW_ENVIRON ||
  185. o->option == TELOPT_OLD_ENVIRON)) {
  186. /*
  187. * We may only have one kind of ENVIRON going at a time.
  188. * This is a hack, but who cares.
  189. */
  190. deactivate_option (o->option==TELOPT_NEW_ENVIRON ? &o_oenv : &o_nenv);
  191. }
  192. if (o->option == TELOPT_ECHO && cfg.ldisc_term)
  193. ldisc = &ldisc_simple;
  194. }
  195. static void refused_option (struct Opt *o) {
  196. if (o->send == WILL && o->option == TELOPT_NEW_ENVIRON &&
  197. o_oenv.state == INACTIVE) {
  198. send_opt (WILL, TELOPT_OLD_ENVIRON);
  199. o_oenv.state = REQUESTED;
  200. }
  201. if (o->option == TELOPT_ECHO && cfg.ldisc_term)
  202. ldisc = &ldisc_term;
  203. }
  204. static void proc_rec_opt (int cmd, int option) {
  205. struct Opt **o;
  206. log_option ("server", cmd, option);
  207. for (o = opts; *o; o++) {
  208. if ((*o)->option == option && (*o)->ack == cmd) {
  209. switch ((*o)->state) {
  210. case REQUESTED:
  211. (*o)->state = ACTIVE;
  212. activate_option (*o);
  213. break;
  214. case ACTIVE:
  215. break;
  216. case INACTIVE:
  217. (*o)->state = ACTIVE;
  218. send_opt ((*o)->send, option);
  219. activate_option (*o);
  220. break;
  221. case REALLY_INACTIVE:
  222. send_opt ((*o)->nsend, option);
  223. break;
  224. }
  225. return;
  226. } else if ((*o)->option == option && (*o)->nak == cmd) {
  227. switch ((*o)->state) {
  228. case REQUESTED:
  229. (*o)->state = INACTIVE;
  230. refused_option (*o);
  231. break;
  232. case ACTIVE:
  233. (*o)->state = INACTIVE;
  234. send_opt ((*o)->nsend, option);
  235. break;
  236. case INACTIVE:
  237. case REALLY_INACTIVE:
  238. break;
  239. }
  240. return;
  241. }
  242. }
  243. /*
  244. * If we reach here, the option was one we weren't prepared to
  245. * cope with. So send a negative ack.
  246. */
  247. send_opt ((cmd == WILL ? DONT : WONT), option);
  248. }
  249. static void process_subneg (void) {
  250. unsigned char b[2048], *p, *q;
  251. int var, value, n;
  252. char *e;
  253. switch (sb_opt) {
  254. case TELOPT_TSPEED:
  255. if (sb_len == 1 && sb_buf[0] == TELQUAL_SEND) {
  256. char logbuf[sizeof(cfg.termspeed)+80];
  257. b[0] = IAC; b[1] = SB; b[2] = TELOPT_TSPEED;
  258. b[3] = TELQUAL_IS;
  259. strcpy(b+4, cfg.termspeed);
  260. n = 4 + strlen(cfg.termspeed);
  261. b[n] = IAC; b[n+1] = SE;
  262. s_write (b, n+2);
  263. logevent("server:\tSB TSPEED SEND");
  264. sprintf(logbuf, "client:\tSB TSPEED IS %s", cfg.termspeed);
  265. logevent (logbuf);
  266. } else
  267. logevent ("server:\tSB TSPEED <something weird>");
  268. break;
  269. case TELOPT_TTYPE:
  270. if (sb_len == 1 && sb_buf[0] == TELQUAL_SEND) {
  271. char logbuf[sizeof(cfg.termtype)+80];
  272. b[0] = IAC; b[1] = SB; b[2] = TELOPT_TTYPE;
  273. b[3] = TELQUAL_IS;
  274. for (n = 0; cfg.termtype[n]; n++)
  275. b[n+4] = (cfg.termtype[n] >= 'a' && cfg.termtype[n] <= 'z' ?
  276. cfg.termtype[n] + 'A'-'a' : cfg.termtype[n]);
  277. b[n+4] = IAC; b[n+5] = SE;
  278. s_write (b, n+6);
  279. b[n+4] = 0;
  280. logevent("server:\tSB TTYPE SEND");
  281. sprintf(logbuf, "client:\tSB TTYPE IS %s", b+4);
  282. logevent(logbuf);
  283. } else
  284. logevent("server:\tSB TTYPE <something weird>\r\n");
  285. break;
  286. case TELOPT_OLD_ENVIRON:
  287. case TELOPT_NEW_ENVIRON:
  288. p = sb_buf;
  289. q = p + sb_len;
  290. if (p < q && *p == TELQUAL_SEND) {
  291. char logbuf[50];
  292. p++;
  293. sprintf (logbuf, "server:\tSB %s SEND", telopt(sb_opt));
  294. logevent (logbuf);
  295. if (sb_opt == TELOPT_OLD_ENVIRON) {
  296. if (cfg.rfc_environ) {
  297. value = RFC_VALUE;
  298. var = RFC_VAR;
  299. } else {
  300. value = BSD_VALUE;
  301. var = BSD_VAR;
  302. }
  303. /*
  304. * Try to guess the sense of VAR and VALUE.
  305. */
  306. while (p < q) {
  307. if (*p == RFC_VAR) {
  308. value = RFC_VALUE;
  309. var = RFC_VAR;
  310. } else if (*p == BSD_VAR) {
  311. value = BSD_VALUE;
  312. var = BSD_VAR;
  313. }
  314. p++;
  315. }
  316. } else {
  317. /*
  318. * With NEW_ENVIRON, the sense of VAR and VALUE
  319. * isn't in doubt.
  320. */
  321. value = RFC_VALUE;
  322. var = RFC_VAR;
  323. }
  324. b[0] = IAC; b[1] = SB; b[2] = sb_opt;
  325. b[3] = TELQUAL_IS;
  326. n = 4;
  327. e = cfg.environmt;
  328. while (*e) {
  329. b[n++] = var;
  330. while (*e && *e != '\t') b[n++] = *e++;
  331. if (*e == '\t') e++;
  332. b[n++] = value;
  333. while (*e) b[n++] = *e++;
  334. e++;
  335. }
  336. if (*cfg.username) {
  337. b[n++] = var; b[n++] = 'U'; b[n++] = 'S';
  338. b[n++] = 'E'; b[n++] = 'R'; b[n++] = value;
  339. e = cfg.username;
  340. while (*e) b[n++] = *e++;
  341. }
  342. b[n++] = IAC; b[n++] = SE;
  343. s_write (b, n);
  344. sprintf(logbuf, "client:\tSB %s IS %s", telopt(sb_opt),
  345. n==6 ? "<nothing>" : "<stuff>");
  346. logevent (logbuf);
  347. }
  348. break;
  349. }
  350. }
  351. static enum {
  352. TOPLEVEL, SEENIAC, SEENWILL, SEENWONT, SEENDO, SEENDONT,
  353. SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR
  354. } telnet_state = TOPLEVEL;
  355. static void do_telnet_read (char *buf, int len) {
  356. unsigned char b[10];
  357. while (len--) {
  358. int c = (unsigned char) *buf++;
  359. switch (telnet_state) {
  360. case TOPLEVEL:
  361. case SEENCR:
  362. if (c == NUL && telnet_state == SEENCR)
  363. telnet_state = TOPLEVEL;
  364. else if (c == IAC)
  365. telnet_state = SEENIAC;
  366. else {
  367. b[0] = c;
  368. if (!in_synch)
  369. c_write (b, 1);
  370. #if 1
  371. /* I can't get the F***ing winsock to insert the urgent IAC
  372. * into the right position! Even with SO_OOBINLINE it gives
  373. * it to recv too soon. And of course the DM byte (that
  374. * arrives in the same packet!) appears several K later!!
  375. *
  376. * Oh well, we do get the DM in the right place so I'll
  377. * just stop hiding on the next 0xf2 and hope for the best.
  378. */
  379. else if (c == DM) in_synch = 0;
  380. #endif
  381. if (c == CR)
  382. telnet_state = SEENCR;
  383. else
  384. telnet_state = TOPLEVEL;
  385. }
  386. break;
  387. case SEENIAC:
  388. if (c == DO) telnet_state = SEENDO;
  389. else if (c == DONT) telnet_state = SEENDONT;
  390. else if (c == WILL) telnet_state = SEENWILL;
  391. else if (c == WONT) telnet_state = SEENWONT;
  392. else if (c == SB) telnet_state = SEENSB;
  393. else if (c == DM) {
  394. in_synch = 0;
  395. telnet_state = TOPLEVEL;
  396. }
  397. else {
  398. /* ignore everything else; print it if it's IAC */
  399. if (c == IAC) {
  400. b[0] = c;
  401. c_write(b,1);
  402. }
  403. telnet_state = TOPLEVEL;
  404. }
  405. break;
  406. case SEENWILL:
  407. proc_rec_opt (WILL, c);
  408. telnet_state = TOPLEVEL;
  409. break;
  410. case SEENWONT:
  411. proc_rec_opt (WONT, c);
  412. telnet_state = TOPLEVEL;
  413. break;
  414. case SEENDO:
  415. proc_rec_opt (DO, c);
  416. telnet_state = TOPLEVEL;
  417. break;
  418. case SEENDONT:
  419. proc_rec_opt (DONT, c);
  420. telnet_state = TOPLEVEL;
  421. break;
  422. case SEENSB:
  423. sb_opt = c;
  424. sb_len = 0;
  425. telnet_state = SUBNEGOT;
  426. break;
  427. case SUBNEGOT:
  428. if (c == IAC)
  429. telnet_state = SUBNEG_IAC;
  430. else {
  431. subneg_addchar:
  432. if (sb_len >= sb_size) {
  433. char *newbuf;
  434. sb_size += SB_DELTA;
  435. newbuf = (sb_buf ?
  436. realloc(sb_buf, sb_size) :
  437. malloc(sb_size));
  438. if (newbuf)
  439. sb_buf = newbuf;
  440. else
  441. sb_size -= SB_DELTA;
  442. }
  443. if (sb_len < sb_size)
  444. sb_buf[sb_len++] = c;
  445. telnet_state = SUBNEGOT;/* in case we came here by goto */
  446. }
  447. break;
  448. case SUBNEG_IAC:
  449. if (c != SE)
  450. goto subneg_addchar; /* yes, it's a hack, I know, but... */
  451. else {
  452. process_subneg();
  453. telnet_state = TOPLEVEL;
  454. }
  455. break;
  456. }
  457. }
  458. }
  459. /*
  460. * Called to set up the Telnet connection. Will arrange for
  461. * WM_NETEVENT messages to be passed to the specified window, whose
  462. * window procedure should then call telnet_msg().
  463. *
  464. * Returns an error message, or NULL on success.
  465. *
  466. * Also places the canonical host name into `realhost'.
  467. */
  468. static char *telnet_init (HWND hwnd, char *host, int port, char **realhost) {
  469. SOCKADDR_IN addr;
  470. struct hostent *h;
  471. unsigned long a;
  472. /*
  473. * Try to find host.
  474. */
  475. if ( (a = inet_addr(host)) == (unsigned long) INADDR_NONE) {
  476. if ( (h = gethostbyname(host)) == NULL)
  477. switch (WSAGetLastError()) {
  478. case WSAENETDOWN: return "Network is down";
  479. case WSAHOST_NOT_FOUND: case WSANO_DATA:
  480. return "Host does not exist";
  481. case WSATRY_AGAIN: return "Host not found";
  482. default: return "gethostbyname: unknown error";
  483. }
  484. memcpy (&a, h->h_addr, sizeof(a));
  485. *realhost = h->h_name;
  486. } else
  487. *realhost = host;
  488. a = ntohl(a);
  489. if (port < 0)
  490. port = 23; /* default telnet port */
  491. /*
  492. * Open socket.
  493. */
  494. s = socket(AF_INET, SOCK_STREAM, 0);
  495. if (s == INVALID_SOCKET)
  496. switch (WSAGetLastError()) {
  497. case WSAENETDOWN: return "Network is down";
  498. case WSAEAFNOSUPPORT: return "TCP/IP support not present";
  499. default: return "socket(): unknown error";
  500. }
  501. {
  502. BOOL b = TRUE;
  503. setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (void *)&b, sizeof(b));
  504. }
  505. /*
  506. * Bind to local address.
  507. */
  508. addr.sin_family = AF_INET;
  509. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  510. addr.sin_port = htons(0);
  511. if (bind (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
  512. switch (WSAGetLastError()) {
  513. case WSAENETDOWN: return "Network is down";
  514. default: return "bind(): unknown error";
  515. }
  516. /*
  517. * Connect to remote address.
  518. */
  519. addr.sin_addr.s_addr = htonl(a);
  520. addr.sin_port = htons((short)port);
  521. if (connect (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
  522. switch (WSAGetLastError()) {
  523. case WSAENETDOWN: return "Network is down";
  524. case WSAECONNREFUSED: return "Connection refused";
  525. case WSAENETUNREACH: return "Network is unreachable";
  526. case WSAEHOSTUNREACH: return "No route to host";
  527. default: return "connect(): unknown error";
  528. }
  529. if (WSAAsyncSelect (s, hwnd, WM_NETEVENT, FD_READ |
  530. FD_WRITE | FD_OOB | FD_CLOSE) == SOCKET_ERROR)
  531. switch (WSAGetLastError()) {
  532. case WSAENETDOWN: return "Network is down";
  533. default: return "WSAAsyncSelect(): unknown error";
  534. }
  535. /*
  536. * Initialise option states.
  537. */
  538. if( cfg.ldisc_term )
  539. {
  540. struct Opt **o;
  541. for (o = opts; *o; o++)
  542. if ((*o)->state == REQUESTED)
  543. (*o)->state = INACTIVE;
  544. }
  545. else
  546. {
  547. struct Opt **o;
  548. for (o = opts; *o; o++)
  549. if ((*o)->state == REQUESTED)
  550. send_opt ((*o)->send, (*o)->option);
  551. }
  552. /*
  553. * Set up SYNCH state.
  554. */
  555. in_synch = FALSE;
  556. return NULL;
  557. }
  558. /*
  559. * Process a WM_NETEVENT message. Will return 0 if the connection
  560. * has closed, or <0 for a socket error.
  561. */
  562. static int telnet_msg (WPARAM wParam, LPARAM lParam) {
  563. int ret;
  564. char buf[256];
  565. /*
  566. * Because reading less than the whole of the available pending
  567. * data can generate an FD_READ event, we need to allow for the
  568. * possibility that FD_READ may arrive with FD_CLOSE already in
  569. * the queue; so it's possible that we can get here even with s
  570. * invalid. If so, we return 1 and don't worry about it.
  571. */
  572. if (s == INVALID_SOCKET)
  573. return 1;
  574. if (WSAGETSELECTERROR(lParam) != 0)
  575. return -WSAGETSELECTERROR(lParam);
  576. switch (WSAGETSELECTEVENT(lParam)) {
  577. case FD_READ:
  578. case FD_CLOSE:
  579. {
  580. int clear_of_oob = 1;
  581. if (ioctlsocket (s, SIOCATMARK, &clear_of_oob) < 0 )
  582. return -20000-WSAGetLastError();
  583. in_synch = !clear_of_oob;
  584. do {
  585. ret = recv(s, buf, sizeof(buf), 0);
  586. if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
  587. return 1;
  588. if (ret < 0) /* any _other_ error */
  589. return -10000-WSAGetLastError();
  590. if (ret == 0) {
  591. s = INVALID_SOCKET;
  592. return 0;
  593. }
  594. do_telnet_read (buf, ret);
  595. } while (in_synch);
  596. }
  597. return 1;
  598. case FD_WRITE:
  599. if (outbuf_head != outbuf_reap)
  600. try_write();
  601. return 1;
  602. }
  603. return 1; /* shouldn't happen, but WTF */
  604. }
  605. /*
  606. * Called to send data down the Telnet connection.
  607. */
  608. static void telnet_send (char *buf, int len) {
  609. char *p;
  610. static unsigned char iac[2] = { IAC, IAC };
  611. static unsigned char cr[2] = { CR, NUL };
  612. static unsigned char nl[2] = { CR, LF };
  613. if (s == INVALID_SOCKET)
  614. return;
  615. p = buf;
  616. while (p < buf+len) {
  617. char *q = p;
  618. while (iswritable((unsigned char)*p) && p < buf+len) p++;
  619. s_write (q, p-q);
  620. while (p < buf+len && !iswritable((unsigned char)*p)) {
  621. s_write ((unsigned char)*p == IAC ? iac : nl, 2);
  622. p++;
  623. }
  624. }
  625. }
  626. /*
  627. * Called to set the size of the window from Telnet's POV.
  628. */
  629. static void telnet_size(void) {
  630. unsigned char b[16];
  631. char logbuf[50];
  632. if (s == INVALID_SOCKET || o_naws.state != ACTIVE)
  633. return;
  634. b[0] = IAC; b[1] = SB; b[2] = TELOPT_NAWS;
  635. b[3] = cols >> 8; b[4] = cols & 0xFF;
  636. b[5] = rows >> 8; b[6] = rows & 0xFF;
  637. b[7] = IAC; b[8] = SE;
  638. s_write (b, 9);
  639. sprintf(logbuf, "client:\tSB NAWS %d,%d",
  640. ((unsigned char)b[3] << 8) + (unsigned char)b[4],
  641. ((unsigned char)b[5] << 8) + (unsigned char)b[6]);
  642. logevent (logbuf);
  643. }
  644. /*
  645. * Send Telnet special codes.
  646. */
  647. static void telnet_special (Telnet_Special code) {
  648. unsigned char b[2];
  649. if (s == INVALID_SOCKET)
  650. return;
  651. b[0] = IAC;
  652. switch (code) {
  653. case TS_AYT: b[1] = AYT; s_write (b, 2); break;
  654. case TS_BRK: b[1] = BREAK; s_write (b, 2); break;
  655. case TS_EC: b[1] = EC; s_write (b, 2); break;
  656. case TS_EL: b[1] = EL; s_write (b, 2); break;
  657. case TS_GA: b[1] = GA; s_write (b, 2); break;
  658. case TS_NOP: b[1] = NOP; s_write (b, 2); break;
  659. case TS_ABORT: b[1] = ABORT; s_write (b, 2); break;
  660. case TS_AO: b[1] = AO; s_write (b, 2); break;
  661. case TS_IP: b[1] = IP; s_write (b, 2); break;
  662. case TS_SUSP: b[1] = SUSP; s_write (b, 2); break;
  663. case TS_EOR: b[1] = EOR; s_write (b, 2); break;
  664. case TS_EOF: b[1] = xEOF; s_write (b, 2); break;
  665. case TS_SYNCH:
  666. outbuf_head = outbuf_reap = 0;
  667. b[1] = DM;
  668. send (s, b, 2, MSG_OOB);
  669. break;
  670. case TS_RECHO:
  671. if (o_echo.state == INACTIVE || o_echo.state == REALLY_INACTIVE) {
  672. o_echo.state = REQUESTED;
  673. send_opt (o_echo.send, o_echo.option);
  674. }
  675. break;
  676. case TS_LECHO:
  677. if (o_echo.state == ACTIVE) {
  678. o_echo.state = REQUESTED;
  679. send_opt (o_echo.nsend, o_echo.option);
  680. }
  681. break;
  682. }
  683. }
  684. Backend telnet_backend = {
  685. telnet_init,
  686. telnet_msg,
  687. telnet_send,
  688. telnet_size,
  689. telnet_special
  690. };