1 /*****************************************************************************
3 * Project ___| | | | _ \| |
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
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 * ------------------------------------------------------------
27 * - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
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 -- */
55 #include <sys/types.h>
62 #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
67 #ifdef HAVE_SYS_SOCKET_H
68 #include <sys/socket.h>
70 #include <netinet/in.h>
72 #include <sys/resource.h>
77 #ifdef HAVE_ARPA_INET_H
78 #include <arpa/inet.h>
83 #include <sys/ioctl.h>
86 #ifdef HAVE_SYS_PARAM_H
87 #include <sys/param.h>
90 #ifdef HAVE_SYS_SELECT_H
91 #include <sys/select.h>
98 #include <curl/curl.h>
101 #include "formdata.h"
102 #include "progress.h"
104 #define _MPRINTF_REPLACE /* use our functions only */
105 #include <curl/mprintf.h>
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);
148 static char subbuffer[SUBBUFSIZE];
149 static char *subpointer, *subend; /* buffer for sub-options */
152 * Telnet receiver states for fsm
163 TS_SB, /* sub-option collection */
164 TS_SE /* looking for sub-option end */
167 /* For negotiation compliant to RFC 1143 */
178 static int us_preferred[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 */
190 /* Set all options to NO */
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 */
208 static void negotiate(struct UrlData *data)
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)
228 if (data->bits.verbose)
232 if (TELCMD_OK(option))
233 printf("%s IAC %s\n", direction, TELCMD(option));
235 printf("%s IAC %d\n", direction, option);
239 fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
240 (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
243 if (TELOPT_OK(option))
244 opt = TELOPT(option);
245 else if (option == TELOPT_EXOPL)
251 printf("%s %s %s\n", direction, fmt, opt);
253 printf("%s %s %d\n", direction, fmt, option);
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];
269 swrite(data->firstsocket, buf, 3);
271 printoption(data, "SENT", cmd, option);
274 void set_remote_option(struct UrlData *data, int option, int newstate)
281 him[option] = WANTYES;
282 send_negotiation(data, DO, option);
286 /* Already enabled */
293 /* Already negotiating for YES, queue the request */
294 himq[option] = OPPOSITE;
297 /* Error: already queued an enable request */
306 /* Error: already negotiating for enable */
309 himq[option] = EMPTY;
320 /* Already disabled */
324 him[option] = WANTNO;
325 send_negotiation(data, DONT, option);
332 /* Already negotiating for NO */
335 himq[option] = EMPTY;
344 himq[option] = OPPOSITE;
354 void rec_will(struct UrlData *data, int option)
359 if(him_preferred[option] == YES)
362 send_negotiation(data, DO, option);
366 send_negotiation(data, DONT, option);
371 /* Already enabled */
378 /* Error: DONT answered by WILL */
382 /* Error: DONT answered by WILL */
384 himq[option] = EMPTY;
396 him[option] = WANTNO;
397 himq[option] = EMPTY;
398 send_negotiation(data, DONT, option);
405 void rec_wont(struct UrlData *data, int option)
410 /* Already disabled */
415 send_negotiation(data, DONT, option);
426 him[option] = WANTYES;
427 himq[option] = EMPTY;
428 send_negotiation(data, DO, option);
441 himq[option] = EMPTY;
448 void set_local_option(struct UrlData *data, int option, int newstate)
455 us[option] = WANTYES;
456 send_negotiation(data, WILL, option);
460 /* Already enabled */
467 /* Already negotiating for YES, queue the request */
468 usq[option] = OPPOSITE;
471 /* Error: already queued an enable request */
480 /* Error: already negotiating for enable */
494 /* Already disabled */
499 send_negotiation(data, WONT, option);
506 /* Already negotiating for NO */
518 usq[option] = OPPOSITE;
528 void rec_do(struct UrlData *data, int option)
533 if(us_preferred[option] == YES)
536 send_negotiation(data, WILL, option);
540 send_negotiation(data, WONT, option);
545 /* Already enabled */
552 /* Error: DONT answered by WILL */
556 /* Error: DONT answered by WILL */
571 himq[option] = EMPTY;
572 send_negotiation(data, WONT, option);
579 void rec_dont(struct UrlData *data, int option)
584 /* Already disabled */
589 send_negotiation(data, WONT, option);
600 us[option] = WANTYES;
602 send_negotiation(data, WILL, option);
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 */
631 if (data->bits.verbose)
635 printf("%s IAC SB ", (direction == '<')? "RCVD":"SENT");
640 i = pointer[length-2];
641 j = pointer[length-1];
643 if (i != IAC || j != SE)
645 printf("(terminated by ");
647 printf("%s ", TELOPT(i));
648 else if (TELCMD_OK(i))
649 printf("%s ", TELCMD(i));
653 printf("%s", TELOPT(j));
654 else if (TELCMD_OK(j))
655 printf("%s", TELCMD(j));
658 printf(", not IAC SE!) ");
665 printf("(Empty suboption?)");
669 if (TELOPT_OK(pointer[0]))
670 printf("%s (unknown)", TELOPT(pointer[0]));
672 printf("%d (unknown)", pointer[i]);
673 for (i = 1; i < length; i++)
674 printf(" %d", pointer[i]);
686 * Look at the sub-option buffer, and try to be helpful to the other
688 * No suboptions are supported yet.
691 static void suboption(struct UrlData *data)
693 printsub(data, '<', (unsigned char *)subbuffer, SB_LEN()+2);
697 void telrcv(struct UrlData *data,
698 unsigned char *inbuf, /* Data received from socket */
699 int count) /* Number of bytes received */
708 switch (telrcv_state)
711 telrcv_state = TS_DATA;
714 break; /* Ignore \0 after CR */
717 data->fwrite((char *)&c, 1, 1, data->out);
723 telrcv_state = TS_IAC;
728 telrcv_state = TS_CR;
731 data->fwrite((char *)&c, 1, 1, data->out);
739 telrcv_state = TS_WILL;
742 telrcv_state = TS_WONT;
745 telrcv_state = TS_DO;
748 telrcv_state = TS_DONT;
752 telrcv_state = TS_SB;
755 data->fwrite((char *)&c, 1, 1, data->out);
761 printoption(data, "RCVD", IAC, c);
764 telrcv_state = TS_DATA;
768 printoption(data, "RCVD", WILL, c);
770 telrcv_state = TS_DATA;
774 printoption(data, "RCVD", WONT, c);
776 telrcv_state = TS_DATA;
780 printoption(data, "RCVD", DO, c);
782 telrcv_state = TS_DATA;
786 printoption(data, "RCVD", DONT, c);
788 telrcv_state = TS_DATA;
794 telrcv_state = TS_SE;
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);
824 printoption(data, "In SUBOPTION processing, RCVD", IAC, c);
825 suboption(data); /* handle sub-option */
826 telrcv_state = TS_IAC;
830 telrcv_state = TS_SB;
834 SB_ACCUM((unsigned char)IAC);
835 SB_ACCUM((unsigned char)SE);
838 suboption(data); /* handle sub-option */
839 telrcv_state = TS_DATA;
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];
856 outbuf[0] = *buffer++;
859 outbuf[out_count++] = IAC;
862 bytes_written = swrite(data->firstsocket, outbuf, out_count);
865 bytes_written = SSL_write(data->ssl, (char *)outbuf, out_count);
868 bytes_written = swrite(data->firstsocket, outbuf, out_count);
870 #endif /* USE_SSLEAY */
874 CURLcode telnet_done(struct connectdata *conn)
879 CURLcode telnet(struct connectdata *conn)
881 struct UrlData *data = conn->data;
882 int sockfd = data->firstsocket;
887 char *buf = data->buffer;
892 FD_ZERO (&readfd); /* clear it */
893 FD_SET (sockfd, &readfd);
900 readfd = keepfd; /* set this every lap in the loop */
902 switch (select (sockfd + 1, &readfd, NULL, NULL, NULL))
904 case -1: /* error, stop reading */
907 case 0: /* timeout */
910 if(FD_ISSET(1, &readfd))
912 nread = read(1, buf, 255);
913 telwrite(data, (unsigned char *)buf, nread);
916 if(FD_ISSET(sockfd, &readfd))
919 nread = sread (sockfd, buf, BUFSIZE - 1);
922 nread = SSL_read (data->ssl, buf, BUFSIZE - 1);
925 nread = sread (sockfd, buf, BUFSIZE - 1);
927 #endif /* USE_SSLEAY */
930 /* if we receive 0 or less here, the server closed the connection and
931 we bail out from this! */
937 telrcv(data, (unsigned char *)buf, nread);