Simulated Telnet Protocol C Language Client Program

First of all, we must understand the telnet protocol. The following two blogs gave me preliminary ideas.
https://www.cnblogs.com/liang-ling/p/5833489.html This one is relatively basic Introduction and explanation of the meaning of IAC commands The program written in C# is very complete. Some of the IAC instruction processing here is a direct reference to his program, so the comments have not been modified. I still use his comments.

After reading the above two articles, you can understand this The content of the program from the second po is relatively simple

utils.h

#ifndef __UTILS__H#define __UTILS__H#include #include #include #include #include #include #include #include #include < errno.h>#include #include #include #include #include #include #include #include #include #include typedef signed long int ssize_t;typedef unsigned long int size_t;ssize_t readn(int fd, void *vptr,size_t n);ssize_t writen(int fd, const void *vptr, size_t n);ssize_t readline(int fd,void *vptr,size_t maxlen);#endif

utils. c

 #include"utils.h"ssize_t readn(int fd, void *vptr,size_t n){ size_t nleft; ssize_t nread; char *ptr; ptr = vptr; nleft = n; while(nleft >0) {if((nread = read(fd,ptr,nleft))<0) {if(errno == EINTR)//error: EAGAIN, which means that under non-blocking, no data arrives at this time, return immediately. nread = 0; //error: EINTR, indicating that it was interrupted by a signal. else return (-1);} else if(nread == 0) break; else /* do nothing */ nleft -= nread; ptr += nread;} ​​return n-nleft;//How many bytes actually read} ssize_t writen(int fd, const void *vptr, size_t n){ size_t nleft; ssize_t nwritten; const char *ptr; ptr = vptr; nleft = n; while(nleft> 0) {if((nwritten = write(fd, ptr,nleft)) <0) {if(nwritten <0 && errno == EINTR) {nwritten = 0;} else return (-1);} else if(nwritten == 0) break; else //nwritten> 0 {/*do nothing*/} nleft = nleft-nwritten; ptr = ptr + nwritten;} return (n- nleft);//how many bytes actually written) ssize_t readline(int fd,void *vptr,size_t maxlen) {ssize_t n =0,rc; char c,*ptr; ptr = vptr; while(1) {if((rc = read(fd,&c,1)) == 1) {*ptr++ = c; n++; if(c =='
') break;} else if (rc == 0) {*ptr =''; return (n -1);} else {if(errno == EINTR) continue ; else return (-1);}} *ptr =''; return n;}

telnet.h

#ifndef __TELNET__H#define __TELNET__H //#define IAC 255//command word#define NUL 0#define BEL 7#define BS 8#define HT 9#define LF ?10#define VT ?11#define FF ?12#define CR? 13#define SE 240#define NOP? 241#define DM 242#define BRK? 243#define IP 244#define AO ​​245#define AYT? 246#define EC 247#define EL 248#define GA 249#define SB 250#define WILL 251#define WONT 252#define DO 253#define DONT 254typedef unsigned char uint8;typedef unsigned int uint32;/ /operation optionstypedef enum tagOPERATION_OPTIONS{ TOPT_BIN = 0, TOPT_ECHO = 1, TOPT_RECN = 2, TOPT_SUPP = 3 }OPERATION_OPTIONS;uint32 get_every_frame(uint8* recvbuf,uint32 len,uint8* sendbuf,uint32 sendlen); #pendiftelnet.c

#include"telnet.h"#include#include#define MAXLINE 1024#define SEND 1#define IS 0static uint32 handle_telnetcmd_from_server(uint8* buf,uint32 len,uint8* resp,uint32 n);static uint32 process_every_frame(uint8* startByte,uint8* endByte,uint8* sendbuf,uint32 startSendByte);uint32 get_every_frame,uint8* recbuflen ,uint32 sendlen){ uint32 i =0,n=0,sum =0; //uint8* p = sendbuf; uint8* pRear = &recvbuf[len]; uint8* startByte = recvbuf; uint8* endByte = recvbuf; printf(" -sum-receivelen----%d-------
",len); printf("receive :<*"); for(i =0;i
"); while(startByte != pRear ) {if(*startByte == IAC) {sum = sum + n; switch(*(++endByte)) {/*fa 250 */case SB:while(*(++endByte) != SE){} ;n = process_every_frame(startByte,endByte,sendbuf,sum);break; /*fb 251 */case WILL:endByte +=2;n = process_every_frame(startByte,endByte,sendbuf,sum);break; /*fc 252 * /case WONT:endByte +=2;n = process_every_frame(startByte,endByte,sendbuf,sum);break; /*fd 253 */case DO:endByte +=2;n = process_every_frame(startByte,endByte,sendbuf,sum) ;break; /*fe 254 */case DONT:endByte +=2;n = process_every_frame(startByte,endByte,sendbuf,sum);break; /* 240 */case SE:break; /* sss */default: break ;}} startByte = endByte;} if(sum> sendlen) {printf("--error3---sum> MAXLINE-----
");} printf("--------- -----sum is %d ----
",sum); return sum;}static uint32 process_every_frame(uint8* startByte,uint8* endByte,uint8* sendbuf,uint32 startSen dByte){ uint8 n = 0; uint8* pstartByte = startByte; while(pstartByte != endByte) {n++; pstartByte++;} return handle_telnetcmd_from_server(startByte,n,&sendbuf[startSendByte],MAXLINE);}static uint32 handle_telnetcmd_from_ufserver(uint8 ,uint32 len,uint8* resp,uint32 n){ uint32 i =0; uint8 *p = resp; OPERATION_OPTIONS optionCode; uint8 cmdCode,ch; uint32 resplen =0; memset(resp,0,len); //first display cmd from server in string printf("--receivelen----%d-------
",len); printf("receive :<*"); for(i =0 ;i
"); if(len <3) {printf("IAC command length is %d less then 3
" ,len); return -1;} //Get the command code cmdCode = buf[1]; //Get the option code optionCode = buf[2]; //response requests from server *p = IAC; resplen++; if(optionCode = = TOPT_ECHO || optionCode == TOPT_SUPP) {if (cmdCode == DO) { //I set the command code I answered to 251 (WILL) to support echo or suppress to continue ch = WILL; *(++p) = ch; *(++p) = optionCode; resplen += 2; } //If the command code is 254(DONT) else if (cmdCode == DONT) {//I set the command code I answered to 252(WONT), that is, I will also "refuse to start" echo or suppress to continue ch = WONT; *(++p)= ch; *(++p)= optionCode; resplen += 2;} //If the command code is 251(WILL) else if (cmdCode == WILL) {//I set The command code I answered is 253 (DO), which means I approve that you use echo or suppression to continue ch = DO; *(++p) = ch; *(++p) = optionCode; resplen += 2; / /break;} //If the received command code is 251(WONT) ​​else if (cmdCode == WONT) ​​{//In response, I also reject the option request to echo or suppress to continue ch = DONT; *(++p) = ch; *(++p)= optionCode; resplen += 2; // break;} //If 250 is received (sb, the start of the flag sub-option) else if (cmdCode == SB) {/* * Because of the start The sub-flag bit is added, and the command length is extended to 4 Byte, * Take the last flag byte as the option code * If the option code byte is 1 (send) * then the postback is 250 (the start of the SB sub-option) + the second byte obtained + 0 (is) + 255 (flag bit IAC) + 240 (end of SE sub-option) */ ch = buf[3]; if (ch == SEND) {ch = SB; *(++p) = ch; *(++p )= optionCode; *(++p)= IS; *(++p)= IAC; *(++p)= SE; resplen += 5;} else {printf("ch != SEND
") ;}} else {/* do nothing */}} else/* If the option code is not 1 or 3 */ {// The following series of representatives, no matter what kind of request you send, I will not do it if (cmdCode == DO ) {ch = WONT; *(++p)= ch; *(++p)= optionCode; resplen += 2;} else if (cmdCode == DONT) {ch = WONT; *(++p)= ch; *(++p)= optionCode; resplen += 2;} else if (cmdCode == WILL) {c h = DONT; *(++p)= ch; *(++p)= optionCode; resplen += 2;} else if (cmdCode == WONT) ​​{ch = DONT; *(++p)= ch; *(++p)= optionCode; resplen += 2;} else {/* do nothing */}} printf("--resplen---%d-------
",resplen); printf("response :<*"); for(i =0 ;i
"); if( n 

client.c

//gcc client.c -o client#include"utils.h"#include"telnet.h"#define IP_ADDRESS "127.0.0.1"#define IP_PORT 23#define SERV_PORT 3333#define MAXLINE 1024typedef struct sockaddr SA;void str_cli(FILE *fp,uint32 sockfd);uint32 max(uint32 a,uint32 b);void ERR_EXIT(char* s);uint32 main(uint32 argc,u int32 **argv){ uint32 sockfd,isReady=0; struct sockaddr_in servaddr; uint32 hname[128]; sockfd = socket(AF_INET,SOCK_STREAM,0); bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET servaddr.sin_port = htons(IP_PORT); servaddr.sin_addr.s_addr = inet_addr(IP_ADDRESS); printf("servaddr: IP is %s, Port is %d
",inet_ntoa(servaddr.sin_addr), ntohs(servaddr.sin_port )); while(connect(sockfd,(SA*)&servaddr,sizeof(servaddr))){}; printf("connect has been ready
"); str_cli(stdin,sockfd); exit(0); return 0 ;}void ERR_EXIT(char* s){ perror(s); exit(EXIT_FAILURE);}void INFO_PRINT(char* s){ printf("%s",s);}uint32 max(uint32 a,uint32 b){ return (a>b?a:b);}void str_cli(FILE *fp,uint32 sockfd){ uint32 maxfdp1,nready;//stdineof; fd_set rset; uint8 buf[MAXLINE]; uint8 respbuff[MAXLINE] = {0} ;; uint32 resplen; uint32 n; uint8 echo_cmd[] = {0xff,0xfb,0x01}; //stdineof = 0; FD_ZERO(&rset); writen(sockfd,echo_ cmd,3); for(;;) {//if(stdineof == 0) FD_SET(fileno(fp),&rset); FD_SET(sockfd,&rset); maxfdp1 = max(fileno(fp),sockfd)+1 ; nready = select(maxfdp1,&rset,NULL,NULL,NULL); if(nready <0) {ERR_EXIT("ERROR!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!");} if(FD_ISSET(sockfd,&rset)) {memset(buf,0,MAXLINE); if((n = read(sockfd,buf,MAXLINE))==0 ) {ERR_EXIT("str_cli:server termination prematurely");} buf[n] =''; //printf("FD_ISSET(sockfd,&rset)-------------%s 
",buf); if(buf[0] == IAC) {memset(respbuff,0,MAXLINE); resplen = get_every_frame(buf,n,respbuff,MAXLINE); writen(sockfd,respbuff,resplen);} else {writen(fileno(stdout),(char *)buf,n);} //writen(fil eno(stdout),buf,n);} if(FD_ISSET(fileno(fp),&rset)) {memset(buf,0,MAXLINE); if((n = readline(fileno(fp),(char *)buf ,MAXLINE)) == 0) {//stdineof = 1;//At this time, EOF is encountered and the FIN sequence is about to occur, so the standard input is unreadable shutdown(sockfd,SHUT_WR); FD_CLR(fileno(fp),&rset) ; INFO_PRINT("nothing input!"); continue;} else if(n >0) {/* do nothing */} else {ERR_EXIT("some error occurred ");} //printf("FD_ISSET(fileno(fp ),&rset)----%d--
",n); //memset(buf,0,MAXLINE); writen(sockfd,(char *)buf,n);} }}

makefile

all:Client_telnet @echo "" @echo "This is telnet Client compile......." @echo "" Client_telnet:client.o utils. o telnet.o gcc -g -o Client_telnet client.o utils.o telnet.o client.o:client.c utils.h telnet.h gcc -g -c client.c utils.o:utils.c utils.h gcc -g -c utils.c telnet.o:telnet.c telnet.h gcc -g -c telnet.c clean:- rm client.o utils.o telnet.o Client_telnet

The source code program used in this program above runs on the Linux system as ./Client_telnet

Then the screenshot is like this :

Share a picture

Share Picture

Share a picture

Above

Leave a Comment

Your email address will not be published.