new
[libcurl.git] / lib / telnet.c
blobd7ab27c53169140e0a2ae14ed5238d80e783b25d
1 /*****************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * The contents of this file are subject to the Mozilla Public License
9 * Version 1.0 (the "License"); you may not use this file except in
10 * compliance with the License. You may obtain a copy of the License at
11 * http://www.mozilla.org/MPL/
13 * Software distributed under the License is distributed on an "AS IS"
14 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
15 * License for the specific language governing rights and limitations
16 * under the License.
18 * The Original Code is Curl.
20 * The Initial Developer of the Original Code is Daniel Stenberg.
22 * Portions created by the Initial Developer are Copyright (C) 1998.
23 * All Rights Reserved.
25 * ------------------------------------------------------------
26 * Main author:
27 * - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
29 * http://curl.haxx.nu
31 * $Source: /cvsroot/curl/curl/lib/telnet.c,v $
32 * $Revision: 1.1.1.1 $
33 * $Date: 1999-12-29 14:21:38 $
34 * $Author: bagder $
35 * $State: Exp $
36 * $Locker: $
38 * ------------------------------------------------------------
40 * This implementation of the TELNET protocol is written by
41 * Linus Nielsen <Linus.Nielsen@haxx.nu>,
42 * with some code snippets stolen from the BSD Telnet client.
44 * The negotiation is performed according to RFC 1143 (D. Bernstein,
45 * "The Q Method of Implementing TELNET Option Negotiation")
47 ****************************************************************************/
49 /* -- WIN32 approved -- */
50 #include <stdio.h>
51 #include <string.h>
52 #include <stdarg.h>
53 #include <stdlib.h>
54 #include <ctype.h>
55 #include <sys/types.h>
56 #include <sys/stat.h>
58 #include <errno.h>
60 #include "setup.h"
62 #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
63 #include <winsock.h>
64 #include <time.h>
65 #include <io.h>
66 #else
67 #ifdef HAVE_SYS_SOCKET_H
68 #include <sys/socket.h>
69 #endif
70 #include <netinet/in.h>
71 #include <sys/time.h>
72 #include <sys/resource.h>
73 #ifdef HAVE_UNISTD_H
74 #include <unistd.h>
75 #endif
76 #include <netdb.h>
77 #ifdef HAVE_ARPA_INET_H
78 #include <arpa/inet.h>
79 #endif
80 #ifdef HAVE_NET_IF_H
81 #include <net/if.h>
82 #endif
83 #include <sys/ioctl.h>
84 #include <signal.h>
86 #ifdef HAVE_SYS_PARAM_H
87 #include <sys/param.h>
88 #endif
90 #ifdef HAVE_SYS_SELECT_H
91 #include <sys/select.h>
92 #endif
95 #endif
97 #include "urldata.h"
98 #include <curl/curl.h>
99 #include "download.h"
100 #include "sendf.h"
101 #include "formdata.h"
102 #include "progress.h"
104 #define _MPRINTF_REPLACE /* use our functions only */
105 #include <curl/mprintf.h>
107 #define TELOPTS
108 #define TELCMDS
109 #define SLC_NAMES
111 #include "arpa_telnet.h"
113 #define SUBBUFSIZE 512
115 #define SB_CLEAR() subpointer = subbuffer;
116 #define SB_TERM() { subend = subpointer; SB_CLEAR(); }
117 #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \
118 *subpointer++ = (c); \
121 #define SB_GET() ((*subpointer++)&0xff)
122 #define SB_PEEK() ((*subpointer)&0xff)
123 #define SB_EOF() (subpointer >= subend)
124 #define SB_LEN() (subend - subpointer)
126 void telwrite(struct UrlData *data,
127 unsigned char *buffer, /* Data to write */
128 int count); /* Number of bytes to write */
130 void telrcv(struct UrlData *data,
131 unsigned char *inbuf, /* Data received from socket */
132 int count); /* Number of bytes received */
134 static void printoption(struct UrlData *data,
135 const char *direction,
136 int cmd, int option);
138 static void negotiate(struct UrlData *data);
139 static void send_negotiation(struct UrlData *data, int cmd, int option);
140 static void set_local_option(struct UrlData *data, int cmd, int option);
141 static void set_remote_option(struct UrlData *data, int cmd, int option);
143 static void printsub(struct UrlData *data,
144 int direction, unsigned char *pointer, int length);
145 static void suboption(struct UrlData *data);
147 /* suboptions */
148 static char subbuffer[SUBBUFSIZE];
149 static char *subpointer, *subend; /* buffer for sub-options */
152 * Telnet receiver states for fsm
154 static enum
156 TS_DATA = 0,
157 TS_IAC,
158 TS_WILL,
159 TS_WONT,
160 TS_DO,
161 TS_DONT,
162 TS_CR,
163 TS_SB, /* sub-option collection */
164 TS_SE /* looking for sub-option end */
165 } telrcv_state;
167 /* For negotiation compliant to RFC 1143 */
168 #define NO 0
169 #define YES 1
170 #define WANTYES 2
171 #define WANTNO 3
173 #define EMPTY 0
174 #define OPPOSITE 1
176 static int us[256];
177 static int usq[256];
178 static int us_preferred[256];
179 static int him[256];
180 static int himq[256];
181 static int him_preferred[256];
183 void init_telnet(struct UrlData *data)
185 telrcv_state = TS_DATA;
187 /* Init suboptions */
188 SB_CLEAR();
190 /* Set all options to NO */
191 memset(us, NO, 256);
192 memset(usq, NO, 256);
193 memset(us_preferred, NO, 256);
194 memset(him, NO, 256);
195 memset(himq, NO, 256);
196 memset(him_preferred, NO, 256);
198 /* Set the options we want */
199 us_preferred[TELOPT_BINARY] = YES;
200 us_preferred[TELOPT_SGA] = YES;
201 him_preferred[TELOPT_BINARY] = YES;
202 him_preferred[TELOPT_SGA] = YES;
204 /* Start negotiating */
205 negotiate(data);
208 static void negotiate(struct UrlData *data)
210 int i;
212 for(i = 0;i < NTELOPTS;i++)
214 if(us_preferred[i] == YES)
215 set_local_option(data, i, YES);
217 if(him_preferred[i] == YES)
218 set_remote_option(data, i, YES);
222 static void printoption(struct UrlData *data,
223 const char *direction, int cmd, int option)
225 char *fmt;
226 char *opt;
228 if (data->conf & CONF_VERBOSE)
230 if (cmd == IAC)
232 if (TELCMD_OK(option))
233 printf("%s IAC %s\n", direction, TELCMD(option));
234 else
235 printf("%s IAC %d\n", direction, option);
237 else
239 fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
240 (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
241 if (fmt)
243 if (TELOPT_OK(option))
244 opt = TELOPT(option);
245 else if (option == TELOPT_EXOPL)
246 opt = "EXOPL";
247 else
248 opt = NULL;
250 if(opt)
251 printf("%s %s %s\n", direction, fmt, opt);
252 else
253 printf("%s %s %d\n", direction, fmt, option);
255 else
256 printf("%s %d %d\n", direction, cmd, option);
261 static void send_negotiation(struct UrlData *data, int cmd, int option)
263 unsigned char buf[3];
265 buf[0] = IAC;
266 buf[1] = cmd;
267 buf[2] = option;
269 swrite(data->firstsocket, buf, 3);
271 printoption(data, "SENT", cmd, option);
274 void set_remote_option(struct UrlData *data, int option, int newstate)
276 if(newstate == YES)
278 switch(him[option])
280 case NO:
281 him[option] = WANTYES;
282 send_negotiation(data, DO, option);
283 break;
285 case YES:
286 /* Already enabled */
287 break;
289 case WANTNO:
290 switch(himq[option])
292 case EMPTY:
293 /* Already negotiating for YES, queue the request */
294 himq[option] = OPPOSITE;
295 break;
296 case OPPOSITE:
297 /* Error: already queued an enable request */
298 break;
300 break;
302 case WANTYES:
303 switch(himq[option])
305 case EMPTY:
306 /* Error: already negotiating for enable */
307 break;
308 case OPPOSITE:
309 himq[option] = EMPTY;
310 break;
312 break;
315 else /* NO */
317 switch(him[option])
319 case NO:
320 /* Already disabled */
321 break;
323 case YES:
324 him[option] = WANTNO;
325 send_negotiation(data, DONT, option);
326 break;
328 case WANTNO:
329 switch(himq[option])
331 case EMPTY:
332 /* Already negotiating for NO */
333 break;
334 case OPPOSITE:
335 himq[option] = EMPTY;
336 break;
338 break;
340 case WANTYES:
341 switch(himq[option])
343 case EMPTY:
344 himq[option] = OPPOSITE;
345 break;
346 case OPPOSITE:
347 break;
349 break;
354 void rec_will(struct UrlData *data, int option)
356 switch(him[option])
358 case NO:
359 if(him_preferred[option] == YES)
361 him[option] = YES;
362 send_negotiation(data, DO, option);
364 else
366 send_negotiation(data, DONT, option);
368 break;
370 case YES:
371 /* Already enabled */
372 break;
374 case WANTNO:
375 switch(himq[option])
377 case EMPTY:
378 /* Error: DONT answered by WILL */
379 him[option] = NO;
380 break;
381 case OPPOSITE:
382 /* Error: DONT answered by WILL */
383 him[option] = YES;
384 himq[option] = EMPTY;
385 break;
387 break;
389 case WANTYES:
390 switch(himq[option])
392 case EMPTY:
393 him[option] = YES;
394 break;
395 case OPPOSITE:
396 him[option] = WANTNO;
397 himq[option] = EMPTY;
398 send_negotiation(data, DONT, option);
399 break;
401 break;
405 void rec_wont(struct UrlData *data, int option)
407 switch(him[option])
409 case NO:
410 /* Already disabled */
411 break;
413 case YES:
414 him[option] = NO;
415 send_negotiation(data, DONT, option);
416 break;
418 case WANTNO:
419 switch(himq[option])
421 case EMPTY:
422 him[option] = NO;
423 break;
425 case OPPOSITE:
426 him[option] = WANTYES;
427 himq[option] = EMPTY;
428 send_negotiation(data, DO, option);
429 break;
431 break;
433 case WANTYES:
434 switch(himq[option])
436 case EMPTY:
437 him[option] = NO;
438 break;
439 case OPPOSITE:
440 him[option] = NO;
441 himq[option] = EMPTY;
442 break;
444 break;
448 void set_local_option(struct UrlData *data, int option, int newstate)
450 if(newstate == YES)
452 switch(us[option])
454 case NO:
455 us[option] = WANTYES;
456 send_negotiation(data, WILL, option);
457 break;
459 case YES:
460 /* Already enabled */
461 break;
463 case WANTNO:
464 switch(usq[option])
466 case EMPTY:
467 /* Already negotiating for YES, queue the request */
468 usq[option] = OPPOSITE;
469 break;
470 case OPPOSITE:
471 /* Error: already queued an enable request */
472 break;
474 break;
476 case WANTYES:
477 switch(usq[option])
479 case EMPTY:
480 /* Error: already negotiating for enable */
481 break;
482 case OPPOSITE:
483 usq[option] = EMPTY;
484 break;
486 break;
489 else /* NO */
491 switch(us[option])
493 case NO:
494 /* Already disabled */
495 break;
497 case YES:
498 us[option] = WANTNO;
499 send_negotiation(data, WONT, option);
500 break;
502 case WANTNO:
503 switch(usq[option])
505 case EMPTY:
506 /* Already negotiating for NO */
507 break;
508 case OPPOSITE:
509 usq[option] = EMPTY;
510 break;
512 break;
514 case WANTYES:
515 switch(usq[option])
517 case EMPTY:
518 usq[option] = OPPOSITE;
519 break;
520 case OPPOSITE:
521 break;
523 break;
528 void rec_do(struct UrlData *data, int option)
530 switch(us[option])
532 case NO:
533 if(us_preferred[option] == YES)
535 us[option] = YES;
536 send_negotiation(data, WILL, option);
538 else
540 send_negotiation(data, WONT, option);
542 break;
544 case YES:
545 /* Already enabled */
546 break;
548 case WANTNO:
549 switch(usq[option])
551 case EMPTY:
552 /* Error: DONT answered by WILL */
553 us[option] = NO;
554 break;
555 case OPPOSITE:
556 /* Error: DONT answered by WILL */
557 us[option] = YES;
558 usq[option] = EMPTY;
559 break;
561 break;
563 case WANTYES:
564 switch(usq[option])
566 case EMPTY:
567 us[option] = YES;
568 break;
569 case OPPOSITE:
570 us[option] = WANTNO;
571 himq[option] = EMPTY;
572 send_negotiation(data, WONT, option);
573 break;
575 break;
579 void rec_dont(struct UrlData *data, int option)
581 switch(us[option])
583 case NO:
584 /* Already disabled */
585 break;
587 case YES:
588 us[option] = NO;
589 send_negotiation(data, WONT, option);
590 break;
592 case WANTNO:
593 switch(usq[option])
595 case EMPTY:
596 us[option] = NO;
597 break;
599 case OPPOSITE:
600 us[option] = WANTYES;
601 usq[option] = EMPTY;
602 send_negotiation(data, WILL, option);
603 break;
605 break;
607 case WANTYES:
608 switch(usq[option])
610 case EMPTY:
611 us[option] = NO;
612 break;
613 case OPPOSITE:
614 us[option] = NO;
615 usq[option] = EMPTY;
616 break;
618 break;
623 static void printsub(struct UrlData *data,
624 int direction, /* '<' or '>' */
625 unsigned char *pointer, /* where suboption data is */
626 int length) /* length of suboption data */
629 int i = 0;
631 if (data->conf & CONF_VERBOSE)
633 if (direction)
635 printf("%s IAC SB ", (direction == '<')? "RCVD":"SENT");
636 if (length >= 3)
638 int j;
640 i = pointer[length-2];
641 j = pointer[length-1];
643 if (i != IAC || j != SE)
645 printf("(terminated by ");
646 if (TELOPT_OK(i))
647 printf("%s ", TELOPT(i));
648 else if (TELCMD_OK(i))
649 printf("%s ", TELCMD(i));
650 else
651 printf("%d ", i);
652 if (TELOPT_OK(j))
653 printf("%s", TELOPT(j));
654 else if (TELCMD_OK(j))
655 printf("%s", TELCMD(j));
656 else
657 printf("%d", j);
658 printf(", not IAC SE!) ");
661 length -= 2;
663 if (length < 1)
665 printf("(Empty suboption?)");
666 return;
669 if (TELOPT_OK(pointer[0]))
670 printf("%s (unknown)", TELOPT(pointer[0]));
671 else
672 printf("%d (unknown)", pointer[i]);
673 for (i = 1; i < length; i++)
674 printf(" %d", pointer[i]);
676 if (direction)
678 printf("\n");
684 * suboption()
686 * Look at the sub-option buffer, and try to be helpful to the other
687 * side.
688 * No suboptions are supported yet.
691 static void suboption(struct UrlData *data)
693 printsub(data, '<', (unsigned char *)subbuffer, SB_LEN()+2);
694 return;
697 void telrcv(struct UrlData *data,
698 unsigned char *inbuf, /* Data received from socket */
699 int count) /* Number of bytes received */
701 unsigned char c;
702 int index = 0;
704 while(count--)
706 c = inbuf[index++];
708 switch (telrcv_state)
710 case TS_CR:
711 telrcv_state = TS_DATA;
712 if (c == '\0')
714 break; /* Ignore \0 after CR */
717 data->fwrite((char *)&c, 1, 1, data->out);
718 continue;
720 case TS_DATA:
721 if (c == IAC)
723 telrcv_state = TS_IAC;
724 break;
726 else if(c == '\r')
728 telrcv_state = TS_CR;
731 data->fwrite((char *)&c, 1, 1, data->out);
732 continue;
734 case TS_IAC:
735 process_iac:
736 switch (c)
738 case WILL:
739 telrcv_state = TS_WILL;
740 continue;
741 case WONT:
742 telrcv_state = TS_WONT;
743 continue;
744 case DO:
745 telrcv_state = TS_DO;
746 continue;
747 case DONT:
748 telrcv_state = TS_DONT;
749 continue;
750 case SB:
751 SB_CLEAR();
752 telrcv_state = TS_SB;
753 continue;
754 case IAC:
755 data->fwrite((char *)&c, 1, 1, data->out);
756 break;
757 case DM:
758 case NOP:
759 case GA:
760 default:
761 printoption(data, "RCVD", IAC, c);
762 break;
764 telrcv_state = TS_DATA;
765 continue;
767 case TS_WILL:
768 printoption(data, "RCVD", WILL, c);
769 rec_will(data, c);
770 telrcv_state = TS_DATA;
771 continue;
773 case TS_WONT:
774 printoption(data, "RCVD", WONT, c);
775 rec_wont(data, c);
776 telrcv_state = TS_DATA;
777 continue;
779 case TS_DO:
780 printoption(data, "RCVD", DO, c);
781 rec_do(data, c);
782 telrcv_state = TS_DATA;
783 continue;
785 case TS_DONT:
786 printoption(data, "RCVD", DONT, c);
787 rec_dont(data, c);
788 telrcv_state = TS_DATA;
789 continue;
791 case TS_SB:
792 if (c == IAC)
794 telrcv_state = TS_SE;
796 else
798 SB_ACCUM(c);
800 continue;
802 case TS_SE:
803 if (c != SE)
805 if (c != IAC)
808 * This is an error. We only expect to get
809 * "IAC IAC" or "IAC SE". Several things may
810 * have happend. An IAC was not doubled, the
811 * IAC SE was left off, or another option got
812 * inserted into the suboption are all possibilities.
813 * If we assume that the IAC was not doubled,
814 * and really the IAC SE was left off, we could
815 * get into an infinate loop here. So, instead,
816 * we terminate the suboption, and process the
817 * partial suboption if we can.
819 SB_ACCUM((unsigned char)IAC);
820 SB_ACCUM(c);
821 subpointer -= 2;
822 SB_TERM();
824 printoption(data, "In SUBOPTION processing, RCVD", IAC, c);
825 suboption(data); /* handle sub-option */
826 telrcv_state = TS_IAC;
827 goto process_iac;
829 SB_ACCUM(c);
830 telrcv_state = TS_SB;
832 else
834 SB_ACCUM((unsigned char)IAC);
835 SB_ACCUM((unsigned char)SE);
836 subpointer -= 2;
837 SB_TERM();
838 suboption(data); /* handle sub-option */
839 telrcv_state = TS_DATA;
841 break;
846 void telwrite(struct UrlData *data,
847 unsigned char *buffer, /* Data to write */
848 int count) /* Number of bytes to write */
850 unsigned char outbuf[2];
851 int out_count = 0;
852 int bytes_written;
854 while(count--)
856 outbuf[0] = *buffer++;
857 out_count = 1;
858 if(outbuf[0] == IAC)
859 outbuf[out_count++] = IAC;
861 #ifndef USE_SSLEAY
862 bytes_written = swrite(data->firstsocket, outbuf, out_count);
863 #else
864 if (data->use_ssl) {
865 bytes_written = SSL_write(data->ssl, (char *)outbuf, out_count);
867 else {
868 bytes_written = swrite(data->firstsocket, outbuf, out_count);
870 #endif /* USE_SSLEAY */
874 UrgError telnet(struct UrlData *data)
876 int sockfd = data->firstsocket;
877 fd_set readfd;
878 fd_set keepfd;
880 bool keepon = TRUE;
881 char *buf = data->buffer;
882 int nread;
884 init_telnet(data);
886 FD_ZERO (&readfd); /* clear it */
887 FD_SET (sockfd, &readfd);
888 FD_SET (1, &readfd);
890 keepfd = readfd;
892 while (keepon)
894 readfd = keepfd; /* set this every lap in the loop */
896 switch (select (sockfd + 1, &readfd, NULL, NULL, NULL))
898 case -1: /* error, stop reading */
899 keepon = FALSE;
900 continue;
901 case 0: /* timeout */
902 break;
903 default: /* read! */
904 if(FD_ISSET(1, &readfd))
906 nread = read(1, buf, 255);
907 telwrite(data, (unsigned char *)buf, nread);
910 if(FD_ISSET(sockfd, &readfd))
912 #ifndef USE_SSLEAY
913 nread = sread (sockfd, buf, BUFSIZE - 1);
914 #else
915 if (data->use_ssl) {
916 nread = SSL_read (data->ssl, buf, BUFSIZE - 1);
918 else {
919 nread = sread (sockfd, buf, BUFSIZE - 1);
921 #endif /* USE_SSLEAY */
924 /* if we receive 0 or less here, the server closed the connection and
925 we bail out from this! */
926 if (nread <= 0) {
927 keepon = FALSE;
928 break;
931 telrcv(data, (unsigned char *)buf, nread);
934 return URG_OK;