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