home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 3 / PDCD_3.iso / internet / netlite / NET / c / TELNET < prev    next >
Text File  |  1993-04-10  |  14KB  |  470 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "dbox.h"
  5. #include "werr.h"
  6. #include "global.h"
  7. #include "mbuf.h"
  8. #include "timer.h"
  9. #include "icmp.h"
  10. #include "netuser.h"
  11. #include "tcp.h"
  12. #include "telnet.h"
  13. #include "session.h"
  14. #include "misc.h"
  15. #include "domain.h"
  16.  
  17. static int  telnet(int32, char *, char *, char *, struct session *);
  18. static int  telnet_error(char *, char *, struct session *); 
  19. static void free_telnet(struct telnet *);
  20. static void willopt(struct telnet *, char);
  21. static void wontopt(struct telnet *, char);
  22. static void doopt(struct telnet *, char);
  23. static void dontopt(struct telnet *, char);
  24. static void answer(struct telnet *, int, int); 
  25.  
  26. #define CTLZ    26
  27.  
  28. #define TELNET_Connect    0
  29. #define TELNET_Host       1
  30. #define TELNET_Port       3
  31.  
  32. extern char nospace[];
  33. extern char badhost[];
  34. int refuse_echo = 0;
  35. int unix_line_mode = 0;    /* if true turn <cr> to <nl> when in line mode */
  36.  
  37. #ifdef  DEBUG
  38. char *t_options[] = {
  39.         "Transmit Binary",
  40.         "Echo",
  41.         "",
  42.         "Suppress Go Ahead",
  43.         "",
  44.         "Status",
  45.         "Timing Mark"
  46. };
  47. #endif
  48.  
  49. void start_telnet(void)
  50. {
  51.         struct session *session;
  52.         char buffer[80];
  53.         char Host[256];
  54.         char Port[5];
  55.         dbox d;
  56.  
  57.         if ((d = dbox_new("TELNET")) == NULL)
  58.                  return;
  59.  
  60.         dbox_setfield(d, TELNET_Host, "");
  61.         dbox_setfield(d, TELNET_Port, "23");
  62.         dbox_show(d);
  63.  
  64.         if (dbox_fillin(d) == TELNET_Connect)
  65.         {
  66.                  dbox_getfield(d, TELNET_Host, Host, 255);
  67.                  dbox_getfield(d, TELNET_Port, Port, 4);
  68.  
  69.                  /* Allocate a session descriptor */
  70.                  sprintf(buffer, "TELNET - %.60s", Host);
  71.                  if ((session = newsession(buffer)) == NULLSESSION)
  72.                  {
  73.                         werr(0, "Too many sessions");
  74.                         return;
  75.                  }
  76.  
  77.                  session->name  = strdup(Host);
  78.                  session->type  = RESOLVING;
  79.                  session->parse = NULLVFP;
  80.  
  81.                  sprintf(buffer, "Resolving %.60s ...\n", Host);
  82.                  Window_Write(session->window, buffer, strlen(buffer));
  83.  
  84.                  resolve_a(Host, Port, NULLCHAR, session, telnet, telnet_error);
  85.         }
  86.  
  87.         dbox_dispose(&d);
  88. }
  89.  
  90. static int telnet_error(char *host, char *message, struct session *s)
  91. {
  92.         char buffer[80];
  93.  
  94.         sprintf(buffer, "Cannot TELNET to %s - %s\n", host, message);
  95.         Window_Write(s->window, buffer, strlen(buffer));
  96.  
  97.         detachsession(s);
  98.  
  99.         return 0; 
  100. }
  101.  
  102. /* Execute user telnet command */
  103. static int telnet(int32 address, char *host, char *port, char *arg2, struct session *s)
  104. {
  105.         char buffer[80];
  106.         struct telnet *tn;
  107.         struct tcb *tcb;
  108.         struct socket lsocket, fsocket;
  109.  
  110.         host = host;
  111.         arg2 = arg2;
  112.  
  113.         lsocket.address = ip_addr;
  114.         lsocket.port    = lport++;
  115.  
  116.         fsocket.address = address;
  117.         fsocket.port    = (atoi(port) > 0) ? atoi(port) : TELNET_PORT;
  118.  
  119.         s->type = TELNET;
  120.         s->addr = fsocket.address;
  121.  
  122.         if ((refuse_echo == 0) && (unix_line_mode != 0))
  123.                 s->parse = unix_send_tel;
  124.         else
  125.                 s->parse = send_tel;
  126.  
  127.         s->echo = 0;
  128.         s->raw  = 1;
  129.  
  130.         /* Create and initialize a Telnet protocol descriptor */
  131.         if((tn = (struct telnet *)calloc(1,sizeof(struct telnet))) == NULLTN)
  132.         {
  133.                 Window_Write(s->window, nospace, strlen(nospace));
  134.                 detachsession(s);
  135.                 return 1;
  136.         }
  137.  
  138.         tn->session = s;        /* Upward pointer */
  139.         tn->state = TS_DATA;
  140.         s->cb.telnet = tn;      /* Downward pointer */
  141.  
  142.         sprintf(buffer, "Trying [%s] ...\n", inet_ntoa(address));
  143.         Window_Write(s->window, buffer, strlen(buffer));
  144.  
  145.         tcb = open_tcp(&lsocket,&fsocket,TCP_ACTIVE,0,
  146.          (void (*)())rcv_char,(void(*)())tn_tx,(void(*)())t_state,0,(char *)tn);
  147.  
  148.         tn->tcb = tcb;  /* Downward pointer */
  149.  
  150.         return 0;
  151. }
  152.  
  153. /* Process typed characters */
  154. void unix_send_tel(struct session *session, char *buf, int16 n)
  155. {
  156.         int i;
  157.  
  158.         for (i=0; (i<n) && (buf[i] != '\r'); i++)
  159.                 ;
  160.         if (buf[i] == '\r') {
  161.                 buf[i] = '\n';
  162.                 n = i+1;
  163.         }
  164.         send_tel(session, buf,n);
  165. }
  166.  
  167. void send_tel(struct session *session, char *buf, int16 n)
  168. {
  169.         struct mbuf *bp;
  170.  
  171.         if(session->cb.telnet == NULLTN || session->cb.telnet->tcb == NULLTCB)
  172.                 return;
  173.         bp = qdata(buf,n);
  174.         send_tcp(session->cb.telnet->tcb, bp);
  175. }
  176.  
  177. /* Process incoming TELNET characters */
  178. void tel_input(register struct telnet *tn, struct mbuf *bp)
  179. {
  180.         char c;
  181.         register char *s;
  182.         char *line;
  183.  
  184.         if ((line = s = malloc(len_mbuf(bp) + 1)) == NULL)
  185.         {
  186.                 free_p(bp);
  187.                 return;
  188.         }
  189.  
  190.         /* Optimization for very common special case -- no special chars */
  191.         if(tn->state == TS_DATA){
  192.                 while(bp != NULLBUF && memchr(bp->data,IAC,bp->cnt) == NULLCHAR){
  193.                         while (bp->cnt-- != 0) *s++ = *bp->data++;
  194.                         bp = free_mbuf(bp);
  195.                 }
  196.         }
  197.  
  198.         while (pullup(&bp,&c,1) == 1) {
  199.                 switch(tn->state){
  200.                 case TS_DATA:
  201.                         if(uchar(c) == IAC){
  202.                                 tn->state = TS_IAC;
  203.                         } else {
  204.                                 if(!tn->remote[TN_TRANSMIT_BINARY])
  205.                                         *s++ = c & 0x7f;
  206.                         }
  207.                         break;
  208.                 case TS_IAC:
  209.                         switch(uchar(c)){
  210.                         case WILL:
  211.                                 tn->state = TS_WILL;
  212.                                 break;
  213.                         case WONT:
  214.                                 tn->state = TS_WONT;
  215.                                 break;
  216.                         case DO:
  217.                                 tn->state = TS_DO;
  218.                                 break;
  219.                         case DONT:
  220.                                 tn->state = TS_DONT;
  221.                                 break;
  222.                         case IAC:
  223.                                 Window_Write(tn->session->window, &c, 1);
  224.                                 tn->state = TS_DATA;
  225.                                 break;
  226.                         default:
  227.                                 tn->state = TS_DATA;
  228.                                 break;
  229.                         }
  230.                         break;
  231.                 case TS_WILL:
  232.                         willopt(tn,c);
  233.                         tn->state = TS_DATA;
  234.                         break;
  235.                 case TS_WONT:
  236.                         wontopt(tn,c);
  237.                         tn->state = TS_DATA;
  238.                         break;
  239.                 case TS_DO:
  240.                         doopt(tn,c);
  241.                         tn->state = TS_DATA;
  242.                         break;
  243.                 case TS_DONT:
  244.                         dontopt(tn,c);
  245.                         tn->state = TS_DATA;
  246.                         break;
  247.                 }
  248.         }
  249.         Window_Write(tn->session->window, line, s - line);
  250.         free(line);
  251. }
  252.  
  253. /* Telnet receiver upcall routine */
  254. void rcv_char(register struct tcb *tcb, int16 cnt)
  255. {
  256.         struct mbuf *bp;
  257.         struct telnet *tn;
  258.  
  259.         if((tn = (struct telnet *)tcb->user) == NULLTN){
  260.                 /* Unknown connection; ignore it */
  261.                 return;
  262.         }
  263.  
  264.         if(recv_tcp(tcb,&bp,cnt) > 0)
  265.                 tel_input(tn,bp);
  266. }
  267.  
  268. /* Handle transmit upcalls. Used only for file uploading */
  269. void tn_tx(struct tcb *tcb, int16 cnt)
  270. {
  271.         tcb = tcb;
  272.         cnt = cnt;
  273. }
  274.  
  275. /* State change upcall routine */
  276. void t_state(register struct tcb *tcb, char old, char new)
  277. {
  278.         char buffer[40];
  279.         struct telnet *tn;
  280.         extern char *tcpstates[];
  281.         extern char *reasons[];
  282.         extern char *unreach[];
  283.         extern char *exceed[];
  284.  
  285.         old = old;
  286.  
  287.         /* Can't add a check for unknown connecti