📄 telnet.c
字号:
/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2003, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id: telnet.c,v 1.47 2003/10/19 05:42:49 bagder Exp $ ***************************************************************************/#include "setup.h"#ifndef CURL_DISABLE_TELNET/* -- WIN32 approved -- */#include <stdio.h>#include <string.h>#include <stdarg.h>#include <stdlib.h>#include <ctype.h>#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#if defined(WIN32)#include <time.h>#include <io.h>#else#ifdef HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#include <netinet/in.h>#include <sys/time.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <netdb.h>#ifdef HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#ifdef HAVE_NET_IF_H#include <net/if.h>#endif#include <sys/ioctl.h>#include <signal.h>#ifdef HAVE_SYS_PARAM_H#include <sys/param.h>#endif#ifdef HAVE_SYS_SELECT_H#include <sys/select.h>#endif#endif#include "urldata.h"#include <curl/curl.h>#include "transfer.h"#include "sendf.h"#define _MPRINTF_REPLACE /* use our functions only */#include <curl/mprintf.h>#define TELOPTS#define TELCMDS#include "arpa_telnet.h"/* The last #include file should be: */#ifdef CURLDEBUG#include "memdebug.h"#endif#define SUBBUFSIZE 512#define CURL_SB_CLEAR(x) x->subpointer = x->subbuffer;#define CURL_SB_TERM(x) { x->subend = x->subpointer; CURL_SB_CLEAR(x); }#define CURL_SB_ACCUM(x,c) \ if (x->subpointer < (x->subbuffer+sizeof x->subbuffer)) { \ *x->subpointer++ = (c); \ }#define CURL_SB_GET(x) ((*x->subpointer++)&0xff)#define CURL_SB_PEEK(x) ((*x->subpointer)&0xff)#define CURL_SB_EOF(x) (x->subpointer >= x->subend)#define CURL_SB_LEN(x) (x->subend - x->subpointer)staticvoid telrcv(struct connectdata *, unsigned char *inbuf, /* Data received from socket */ int count); /* Number of bytes received */static void printoption(struct SessionHandle *data, const char *direction, int cmd, int option);static void negotiate(struct connectdata *);static void send_negotiation(struct connectdata *, int cmd, int option);static void set_local_option(struct connectdata *, int cmd, int option);static void set_remote_option(struct connectdata *, int cmd, int option);static void printsub(struct SessionHandle *data, int direction, unsigned char *pointer, int length);static void suboption(struct connectdata *);/* For negotiation compliant to RFC 1143 */#define CURL_NO 0#define CURL_YES 1#define CURL_WANTYES 2#define CURL_WANTNO 3#define CURL_EMPTY 0#define CURL_OPPOSITE 1/* * Telnet receiver states for fsm */typedef enum{ CURL_TS_DATA = 0, CURL_TS_IAC, CURL_TS_WILL, CURL_TS_WONT, CURL_TS_DO, CURL_TS_DONT, CURL_TS_CR, CURL_TS_SB, /* sub-option collection */ CURL_TS_SE /* looking for sub-option end */} TelnetReceive;struct TELNET { int please_negotiate; int already_negotiated; int us[256]; int usq[256]; int us_preferred[256]; int him[256]; int himq[256]; int him_preferred[256]; char subopt_ttype[32]; /* Set with suboption TTYPE */ char subopt_xdisploc[128]; /* Set with suboption XDISPLOC */ struct curl_slist *telnet_vars; /* Environment variables */ /* suboptions */ char subbuffer[SUBBUFSIZE]; char *subpointer, *subend; /* buffer for sub-options */ TelnetReceive telrcv_state;};staticCURLcode init_telnet(struct connectdata *conn){ struct TELNET *tn; tn = (struct TELNET *)malloc(sizeof(struct TELNET)); if(!tn) return CURLE_OUT_OF_MEMORY; conn->proto.telnet = (void *)tn; /* make us known */ memset(tn, 0, sizeof(struct TELNET)); tn->telrcv_state = CURL_TS_DATA; /* Init suboptions */ CURL_SB_CLEAR(tn); /* Set all options to NO */#if 0 /* NO is zero => default fill pattern */ memset(tn->us, CURL_NO, 256); memset(tn->usq, CURL_NO, 256); memset(tn->us_preferred, CURL_NO, 256); memset(tn->him, CURL_NO, 256); memset(tn->himq, CURL_NO, 256); memset(tn->him_preferred, CURL_NO, 256);#endif /* Set the options we want by default */ tn->us_preferred[CURL_TELOPT_BINARY] = CURL_YES; tn->us_preferred[CURL_TELOPT_SGA] = CURL_YES; tn->him_preferred[CURL_TELOPT_BINARY] = CURL_YES; tn->him_preferred[CURL_TELOPT_SGA] = CURL_YES; return CURLE_OK;}static void negotiate(struct connectdata *conn){ int i; struct TELNET *tn = (struct TELNET *)conn->proto.telnet; for(i = 0;i < CURL_NTELOPTS;i++) { if(tn->us_preferred[i] == CURL_YES) set_local_option(conn, i, CURL_YES); if(tn->him_preferred[i] == CURL_YES) set_remote_option(conn, i, CURL_YES); }}static void printoption(struct SessionHandle *data, const char *direction, int cmd, int option){ const char *fmt; const char *opt; if (data->set.verbose) { if (cmd == CURL_IAC) { if (CURL_TELCMD_OK(option)) Curl_infof(data, "%s IAC %s\n", direction, CURL_TELCMD(option)); else Curl_infof(data, "%s IAC %d\n", direction, option); } else { fmt = (cmd == CURL_WILL) ? "WILL" : (cmd == CURL_WONT) ? "WONT" : (cmd == CURL_DO) ? "DO" : (cmd == CURL_DONT) ? "DONT" : 0; if (fmt) { if (CURL_TELOPT_OK(option)) opt = CURL_TELOPT(option); else if (option == CURL_TELOPT_EXOPL) opt = "EXOPL"; else opt = NULL; if(opt) Curl_infof(data, "%s %s %s\n", direction, fmt, opt); else Curl_infof(data, "%s %s %d\n", direction, fmt, option); } else Curl_infof(data, "%s %d %d\n", direction, cmd, option); } }}static void send_negotiation(struct connectdata *conn, int cmd, int option){ unsigned char buf[3]; buf[0] = CURL_IAC; buf[1] = cmd; buf[2] = option; (void)swrite(conn->firstsocket, buf, 3); printoption(conn->data, "SENT", cmd, option);}staticvoid set_remote_option(struct connectdata *conn, int option, int newstate){ struct TELNET *tn = (struct TELNET *)conn->proto.telnet; if(newstate == CURL_YES) { switch(tn->him[option]) { case CURL_NO: tn->him[option] = CURL_WANTYES; send_negotiation(conn, CURL_DO, option); break; case CURL_YES: /* Already enabled */ break; case CURL_WANTNO: switch(tn->himq[option]) { case CURL_EMPTY: /* Already negotiating for CURL_YES, queue the request */ tn->himq[option] = CURL_OPPOSITE; break; case CURL_OPPOSITE: /* Error: already queued an enable request */ break; } break; case CURL_WANTYES: switch(tn->himq[option]) { case CURL_EMPTY: /* Error: already negotiating for enable */ break; case CURL_OPPOSITE: tn->himq[option] = CURL_EMPTY; break; } break; } } else /* NO */ { switch(tn->him[option]) { case CURL_NO: /* Already disabled */ break; case CURL_YES: tn->him[option] = CURL_WANTNO; send_negotiation(conn, CURL_DONT, option); break; case CURL_WANTNO: switch(tn->himq[option]) { case CURL_EMPTY: /* Already negotiating for NO */ break; case CURL_OPPOSITE: tn->himq[option] = CURL_EMPTY; break; } break; case CURL_WANTYES: switch(tn->himq[option]) { case CURL_EMPTY: tn->himq[option] = CURL_OPPOSITE; break; case CURL_OPPOSITE: break; } break; } }}staticvoid rec_will(struct connectdata *conn, int option){ struct TELNET *tn = (struct TELNET *)conn->proto.telnet; switch(tn->him[option]) { case CURL_NO: if(tn->him_preferred[option] == CURL_YES) { tn->him[option] = CURL_YES; send_negotiation(conn, CURL_DO, option); } else { send_negotiation(conn, CURL_DONT, option); } break; case CURL_YES: /* Already enabled */ break; case CURL_WANTNO: switch(tn->himq[option]) { case CURL_EMPTY: /* Error: DONT answered by WILL */ tn->him[option] = CURL_NO; break; case CURL_OPPOSITE: /* Error: DONT answered by WILL */ tn->him[option] = CURL_YES; tn->himq[option] = CURL_EMPTY; break; } break; case CURL_WANTYES: switch(tn->himq[option]) { case CURL_EMPTY: tn->him[option] = CURL_YES; break; case CURL_OPPOSITE: tn->him[option] = CURL_WANTNO; tn->himq[option] = CURL_EMPTY; send_negotiation(conn, CURL_DONT, option); break; } break; }} staticvoid rec_wont(struct connectdata *conn, int option){ struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -