1 char *cktelv = "Telnet support, 9.0.274, 16 Mar 2010";
4 int sstelnet = 0; /* Do server-side Telnet negotiation */
6 /* C K C T E L -- Telnet support */
10 Telnet protocol by Frank da Cruz and Jeffrey Altman.
11 Telnet Forward X by Jeffrey Altman
12 Telnet START_TLS support by Jeffrey Altman
13 Telnet AUTH and ENCRYPT support by Jeffrey Altman
14 Telnet COMPORT support by Jeffrey Altman
15 Telnet NEW-ENVIRONMENT support by Jeffrey Altman
16 Telnet NAWS support by Frank da Cruz and Jeffrey Altman
17 Telnet TERMTYPE support by Jeffrey Altman
18 Telnet KERMIT support by Jeffrey Altman
19 Other contributions as indicated in the code.
21 Copyright (C) 1985, 2010,
22 Trustees of Columbia University in the City of New York.
23 All rights reserved. See the C-Kermit COPYING.TXT file or the
24 copyright text in the ckcmai.c module for disclaimer and permissions.
28 NOTE TO CONTRIBUTORS: This file, and all the other shared (ckc and cku)
29 C-Kermit source files, must be compatible with C preprocessors that support
30 only #ifdef, #else, #endif, #define, and #undef. Please do not use #if,
31 logical operators, or other preprocessor features in this module. Also,
32 don't use any ANSI C constructs except within #ifdef CK_ANSIC..#endif.
40 #define TELCMDS /* to define name array */
41 #define TELOPTS /* to define name array */
42 #define SLC_NAMES /* to define name array */
50 #ifdef CK_AUTHENTICATION
52 #endif /* CK_AUTHENTICATION */
58 #ifdef OS2 /* For terminal type name string */
64 #define isascii __isascii
67 extern int tt_type, max_tt;
68 extern struct tt_info_rec tt_info[];
84 #ifdef CK_NAWS /* Negotiate About Window Size */
86 _PROTOTYP( int rlog_naws, (void) );
90 int tn_init = 0; /* Telnet protocol initialized flag */
91 int tn_begun = 0; /* Telnet protocol started flag */
92 static int tn_first = 1; /* First time init flag */
93 extern int tn_exit; /* Exit on disconnect */
95 extern int inserver; /* Running as IKSD */
96 char *tn_term = NULL; /* Terminal type override */
99 char *tn_loc = NULL; /* Location override */
100 #endif /* CK_SNDLOC */
101 int tn_nlm = TNL_CRLF; /* Telnet CR -> CR LF mode */
102 int tn_b_nlm = TNL_CR; /* Telnet Binary CR RAW mode */
103 int tn_b_meu = 0; /* Telnet Binary ME means U too */
104 int tn_b_ume = 0; /* Telnet Binary U means ME too */
105 int tn_wait_flg = 1; /* Telnet Wait for Negotiations */
106 int tn_infinite = 0; /* Telnet Bug Infinite-Loop-Check */
107 int tn_rem_echo = 1; /* We will echo if WILL ECHO */
108 int tn_b_xfer = 0; /* Telnet Binary for Xfers? */
109 int tn_sb_bug = 1; /* Telnet BUG - SB w/o WILL or DO */
110 int tn_auth_krb5_des_bug = 1; /* Telnet BUG - AUTH KRB5 DES */
111 /* truncates long keys */
112 int tn_no_encrypt_xfer = 0; /* Turn off Telnet Encrypt? */
113 int tn_delay_sb = 1; /* Delay SBs until safe */
114 int tn_auth_how = TN_AUTH_HOW_ANY;
115 int tn_auth_enc = TN_AUTH_ENC_ANY;
116 int tn_deb = 0; /* Telnet Debug mode */
117 int tn_sfu = 0; /* Microsoft SFU compatibility */
119 char * tn_fwdx_xauthority = NULL; /* Xauthority File */
120 int fwdx_no_encrypt = 0; /* Forward-X requires encryption */
121 #endif /* CK_FORWARD_X */
124 int ttnum = -1; /* Last Telnet Terminal Type sent */
125 int ttnumend = 0; /* Has end of list been found */
128 char tn_msg[TN_MSG_LEN]; /* Telnet data can be rather long */
129 char hexbuf[TN_MSG_LEN];
130 char tn_msg_out[TN_MSG_LEN];
132 CHAR fwdx_msg_out[TN_MSG_LEN];
133 #endif /* CK_FORWARD_X */
136 In order to prevent an infinite telnet negotiation loop we maintain a
137 count of the number of times the same telnet negotiation message is
138 sent. When this count hits MAXTNCNT, we do not send any more of the
139 message. The count is stored in the tncnts[][] array.
141 The tncnts[][] array is indexed by negotiation option (SUPPRESS GO AHEAD,
142 TERMINAL TYPE, NAWS, etc. - see the tnopts[] array) and the four
143 negotiation message types (WILL, WONT, DO, DONT). All telnet negotiations
144 are kept track of in this way.
146 The count for a message is zeroed when the "opposite" message is sent.
147 WILL is the opposite of WONT, and DO is the opposite of DONT.
148 For example sending "WILL SGA" increments tncnts[TELOPT_SGA][0]
149 and zeroes tncnts[TELOPT_SGA][1].
151 The code that does this is in tn_sopt().
153 rogersh@fsj.co.jp, 18/3/1995
155 8/16/1998 - with the recent rewrite of the telnet state machine I don't
156 think this code is necessary anymore. However, it can't do any harm so
157 I am leaving it in. - Jeff
159 12/28/1998 - all references to tncnts[] must be done with TELOPT_INDEX(opt)
160 because the Telnet option list is no longer contiguous. We also must
161 allocate NTELOPTS + 1 because the TELOPT_INDEX() macro returns NTELOPTS
162 for an invalid option number.
165 #define MAXTNCNT 4 /* Permits 4 intermediate telnet firewalls/gateways */
167 char tncnts[NTELOPTS+1][4]; /* Counts */
168 char tnopps[4] = { 1,0,3,2 }; /* Opposites */
170 #ifdef CK_ENVIRONMENT
172 #define TSBUFSIZ 2056
173 #else /* CK_FORWARD_X */
174 #define TSBUFSIZ 1024
175 #endif /* CK_FORWARD_X */
176 char tn_env_acct[64];
177 char tn_env_disp[64];
179 char tn_env_prnt[64];
181 char * tn_env_uservar[8][2];
183 #else /* CK_ENVIRONMENT */
186 #endif /* CK_ENVIRONMENT */
189 /* SIGWINCH handler moved to ckuusx.c */
191 #ifdef CK_NAWS /* Window size business */
196 #endif /* NOSIGWINCH */
199 CHAR sb[TSBUFSIZ]; /* Buffer - incoming subnegotiations */
200 CHAR sb_out[TSBUFSIZ]; /* Buffer - outgoing subnegotiations */
202 int tn_duplex = 1; /* Local echo */
204 extern char uidbuf[]; /* User ID buffer */
205 extern int quiet, ttnet, ttnproto, debses, what, duplex, oldplex, local;
206 extern int seslog, sessft, whyclosed;
209 extern int tt_rows[], tt_cols[];
210 extern int tt_status[VNUM];
211 extern int scrninitialized[];
214 extern int tt_rows, tt_cols; /* Everybody has this */
216 extern int cmd_cols, cmd_rows;
217 extern char namecopy[];
218 extern char myipaddr[]; /* Global copy of my IP address */
222 telopt_index(opt) int opt; {
223 if (opt >= 0 && opt <= TELOPT_STDERR)
225 else if (opt >= TELOPT_PRAGMA_LOGON && opt <= TELOPT_PRAGMA_HEARTBEAT)
227 else if (opt == TELOPT_IBM_SAK)
234 telopt_ok(opt) int opt; {
235 return((opt >= TELOPT_BINARY && opt <= TELOPT_STDERR) ||
236 (opt >= TELOPT_PRAGMA_LOGON && opt <= TELOPT_PRAGMA_HEARTBEAT) ||
237 (opt == TELOPT_IBM_SAK));
241 telopt(opt) int opt; {
243 return((CHAR *)telopts[telopt_index(opt)]);
245 return((CHAR *)"UNKNOWN");
249 telopt_mode_ok(opt) int opt; {
250 return((unsigned int)(opt) <= TN_NG_MU);
254 telopt_mode(opt) int opt; {
255 if (telopt_mode_ok(opt))
256 return((CHAR *)telopt_modes[opt-TN_NG_RF]);
258 return((CHAR *)"UNKNOWN");
260 #endif /* TELOPT_MACRO */
263 tn_outst(notquiet) int notquiet; {
269 #endif /* CK_ENCRYPTION */
272 for (x = TELOPT_FIRST; x <= TELOPT_LAST; x++) {
274 if (TELOPT_UNANSWERED_WILL(x)) {
276 printf("?Telnet waiting for response to WILL %s\r\n",
278 debug(F111,"tn_outst","unanswered WILL",x);
283 if (TELOPT_UNANSWERED_DO(x)) {
285 printf("?Telnet waiting for response to DO %s\r\n",
287 debug(F111,"tn_outst","unanswered DO",x);
292 if (TELOPT_UNANSWERED_WONT(x)) {
294 printf("?Telnet waiting for response to WONT %s\r\n",
296 debug(F111,"tn_outst","unanswered WONT",x);
301 if (TELOPT_UNANSWERED_DONT(x)) {
303 printf("?Telnet waiting for response to DONT %s\r\n",
305 debug(F111,"tn_outst","unanswered DONT",x);
310 if (TELOPT_UNANSWERED_SB(x)) {
312 printf("?Telnet waiting for response to SB %s\r\n",
314 debug(F111,"tn_outst","unanswered SB",x);
321 #ifdef CK_AUTHENTICATION
322 if (ck_tn_auth_in_progress()) {
323 if (TELOPT_ME(TELOPT_AUTHENTICATION)) {
325 printf("?Telnet waiting for WILL %s subnegotiation\r\n",
326 TELOPT(TELOPT_AUTHENTICATION));
329 "ME authentication in progress",
330 TELOPT_AUTHENTICATION
333 } else if (TELOPT_U(TELOPT_AUTHENTICATION)) {
335 printf("?Telnet waiting for DO %s subnegotiation\r\n",
336 TELOPT(TELOPT_AUTHENTICATION));
339 "U authentication in progress",
340 TELOPT_AUTHENTICATION
345 #endif /* CK_AUTHENTICATION */
348 e = ck_tn_encrypting();
349 d = ck_tn_decrypting();
350 if (TELOPT_ME(TELOPT_ENCRYPTION)) {
351 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && e ||
352 !TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && !e
355 printf("?Telnet waiting for WILL %s subnegotiation\r\n",
356 TELOPT(TELOPT_ENCRYPTION));
359 "encryption mode switch",
365 if (TELOPT_U(TELOPT_ENCRYPTION)) {
366 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && d ||
367 !TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && !d
370 printf("?Telnet waiting for DO %s subnegotiation\r\n",
371 TELOPT(TELOPT_ENCRYPTION));
374 "decryption mode switch",
381 #endif /* CK_ENCRYPTION */
382 } /* if (tn_wait_flg) */
385 /* Even if we are not waiting for Telnet options we must wait for */
386 /* Kermit Telnet Subnegotiations if we have sent a request to the */
387 /* other guy. Otherwise we will get out of sync. */
389 if (TELOPT_U(TELOPT_KERMIT) &&
390 (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start ||
391 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop ||
392 !TELOPT_SB(TELOPT_KERMIT).kermit.sop)
395 printf("?Telnet waiting for SB %s negotiation\r\n",
396 TELOPT(TELOPT_KERMIT));
397 debug(F111,"tn_outst","U kermit in progress",TELOPT_KERMIT);
401 #endif /* IKS_OPTION */
405 if (TELOPT_ME(TELOPT_COMPORT)) {
406 if (TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb) {
408 printf("?Telnet waiting for SB %s negotiation\r\n",
409 TELOPT(TELOPT_COMPORT));
410 debug(F111,"tn_outst","ComPort SB in progress",TELOPT_COMPORT);
413 if (TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms) {
415 printf("?Telnet waiting for SB %s MODEM_STATUS negotiation\r\n",
416 TELOPT(TELOPT_COMPORT));
417 debug(F111,"tn_outst","ComPort SB MS in progress",TELOPT_COMPORT);
422 #endif /* TN_COMPORT */
429 if (!local) return(0);
430 if (ttnet != NET_TCPB) return(0);
431 if (ttnproto != NP_TELNET) return(0);
432 if (TELOPT_ME(TELOPT_COMPORT))
435 #endif /* TN_COMPORT */
439 /* tn_wait() -- Wait for response to Telnet negotiation. */
441 Wait for up to <timeout> seconds for the response to arrive.
442 Place all non-telnet data into Telnet Wait Buffer.
443 If response does arrive return 1, else return 0.
445 #ifndef TN_WAIT_BUF_SZ
446 #define TN_WAIT_BUF_SZ 4096
447 #endif /* TN_WAIT_BUF_SZ */
448 static char tn_wait_buf[TN_WAIT_BUF_SZ];
449 static int tn_wait_idx = 0;
451 #define TN_TIMEOUT 120
452 #endif /* TN_TIMEOUT */
453 static int tn_wait_tmo = TN_TIMEOUT;
457 prtwait(state) int state; {
473 #endif /* CKSPINNER */
475 static int nflag = 0;
479 tn_wait(char * where)
481 tn_wait(where) char * where;
482 #endif /* CK_ANSIC */
484 extern int ckxech, local;
485 int ch = 0, count = 0;
494 #endif /* TN_COMPORT */
496 /* if (!IS_TELNET()) return(1); */
500 debug(F110,"tn_wait waiting for",where,0);
501 tn_wait_tmo = TN_TIMEOUT;
502 debug(F111,"tn_wait","timeout",tn_wait_tmo);
503 outstanding = tn_outst(0);
504 debug(F111,"tn_wait","outstanding",outstanding);
505 debug(F111,"tn_wait","tn_wait_flg",tn_wait_flg);
507 /* The following is meant to be !(||). We only want to return */
508 /* immediately if both the tn_wait_flg && tn_outst() are false */
509 if (!(outstanding || tn_wait_flg)) /* If no need to wait */
510 return(1); /* Don't. */
512 if (tn_deb || debses) tn_debug("<wait for outstanding negotiations>");
515 if (!sstelnet && !quiet)
517 #endif /* CKSPINNER */
519 /* Wait up to TN_TIMEOUT sec for responses to outstanding telnet negs */
525 if (ch == -1) { /* Timed out */
526 if (!sstelnet && !quiet) { /* Let user know... */
532 printf(" Negotiations.");
540 #endif /* CKSPINNER */
542 } else if (ch < -1) {
543 printf("\r\n?Connection closed by peer.\r\n");
544 if (tn_deb || debses) tn_debug("<connection closed by peer>");
550 if (!sstelnet && !quiet)
552 #endif /* CKSPINNER */
553 ch = tn_doop((CHAR)(ch & 0xff),inserver?ckxech:duplex,ttinc);
555 if (!sstelnet && !quiet) {
558 #endif /* CKSPINNER */
559 debug(F101,"tn_wait tn_doop","",ch);
562 duplex = 1; /* Turn on echoing */
567 duplex = 0; /* Turn off echoing */
572 tn_wait_buf[tn_wait_idx++] = IAC;
574 case 4: /* IKS event */
579 printf("?Telnet Option negotiation error.\n");
580 if (tn_deb || debses)
581 tn_debug("<Telnet Option negotiation error>");
584 printf("?Connection closed by peer.\n");
585 if (tn_deb || debses) tn_debug("<Connection closed by peer>");
590 if (tn_deb || debses) tn_debug("<Unknown connection error>");
597 if (!sstelnet && !quiet) {
601 #endif /* CKSPINNER */
602 tn_wait_buf[tn_wait_idx++] = (CHAR)(ch & 0xff);
605 outstanding = tn_outst(0);
607 if ( outstanding && ch != IAC ) {
608 int timer = gtimer();
609 if ( timer > tn_wait_tmo ) {
612 "\r\n?Telnet Protocol Timeout - connection closed\r\n");
613 if (tn_deb || debses)
615 "<telnet protocol timeout - connection closed>");
618 /* if we do not close the connection, then we will block */
619 /* the next time we hit a wait. and if we don't we will */
620 /* do the wrong thing if the host sends 0xFF and does */
621 /* not intend it to be an IAC. */
623 whyclosed = WC_TELOPT;
627 else if ( hints && timer > 30 && nohintgiven && !inserver ) {
630 #else /* CKSPINNER */
632 #endif /* CKSPINNER */
633 printf("*************************\r\n");
634 printf("The Telnet %s is not sending required responses.\r\n\r\n",
635 sstelnet?"client":"server");
637 printf("\nYou can continue to wait or you can cancel with Ctrl-C.\r\n");
638 printf("In case the Telnet server never responds as required,\r\n");
639 printf("you can try connecting to this host with TELNET /NOWAIT.\r\n");
640 printf("Use SET HINTS OFF to suppress further hints.\r\n");
641 printf("*************************\r\n");
648 /* Must disable carrier detect check if we are using Telnet Comport */
653 #else /* TN_COMPORT */
655 #endif /* TN_COMPORT */
656 } while ((tn_wait_idx < TN_WAIT_BUF_SZ) &&
657 (outstanding && count >= 0));
659 if (tn_wait_idx == TN_WAIT_BUF_SZ) {
660 if (tn_deb || debses) tn_debug("<Telnet Wait Buffer filled>");
664 if (!sstelnet && !quiet) {
672 #endif /* CKSPINNER */
674 if (tn_deb || debses) tn_debug("<no outstanding negotiations>");
678 /* Push data from the Telnet Wait Buffer into the I/O Queue */
679 /* Return 1 on success */
684 extern int tt_push_inited;
685 #endif /* NETLEBUF */
686 /* if (!IS_TELNET()) return(1); */
689 ckhexdump((CHAR *)"tn_push",tn_wait_buf,tn_wait_idx);
691 if (!tt_push_inited) /* Local handling */
693 le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
694 #else /* External handling... */
695 #ifdef OS2 /* K95 has its own way */
696 le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
698 #ifdef TTLEBUF /* UNIX, etc */
699 le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
702 If you see this message in AOS/VS, OS-9, VOS, etc, you need to copy
703 the #ifdef TTLEBUF..#endif code from ckutio.c to the corresponding
704 places in your ck?tio.c module.
706 printf("tn_push called but not implemented - data lost.\n");
709 #endif /* NETLEBUF */
712 tn_wait_tmo = TN_TIMEOUT; /* Reset wait timer stats */
718 Sends a telnet option, avoids loops.
719 Returns 1 if command was sent, 0 if not, -1 on error.
722 tn_sopt(cmd,opt) int cmd, opt; { /* TELNET SEND OPTION */
726 if (ttnet != NET_TCPB) return(-1); /* Must be TCP/IP */
727 if (ttnproto != NP_TELNET) return(-1); /* Must be telnet protocol */
728 if (!TELCMD_OK(cmd)) return(-1);
729 if (TELOPT_OK(opt)) {
730 if (cmd == DO && TELOPT_UNANSWERED_DO(opt)) return(0);
731 if (cmd == WILL && TELOPT_UNANSWERED_WILL(opt)) return(0);
732 if (cmd == DONT && TELOPT_UNANSWERED_DONT(opt)) return(0);
733 if (cmd == WONT && TELOPT_UNANSWERED_WONT(opt)) return(0);
736 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
741 if (cmd == DO && opt == TELOPT_AUTHENTICATION)
744 if (tn_infinite && TELOPT_OK(opt)) { /* See comment above about */
745 int index = TELOPT_INDEX(opt); /* preventing infinite loops */
748 if (tncnts[index][m] > MAXTNCNT) {
750 if (tn_deb || debses || deblog) {
751 ckmakmsg(msg,sizeof(msg),
752 "TELNET negotiation loop ",
755 debug(F101,msg,"",opt);
756 if (tn_deb || debses) tn_debug(msg);
762 tncnts[index][tnopps[m]] = 0;
765 buf[1] = (CHAR) (cmd & 0xff);
766 buf[2] = (CHAR) (opt & 0xff);
769 if ((tn_deb || debses || deblog) && cmd != SB)
770 ckmakmsg(msg,sizeof(msg),"TELNET SENT ",TELCMD(cmd)," ",
774 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
776 debug(F101,msg,"",opt);
777 if ((tn_deb || debses) && cmd != SB)
779 rc = (ttol(buf,3) < 3);
781 ReleaseTelnetMutex();
787 if (TELOPT_OK(opt)) {
788 if (cmd == DONT && TELOPT_UNANSWERED_DO(opt))
789 TELOPT_UNANSWERED_DO(opt) = 0;
790 if (cmd == WONT && TELOPT_UNANSWERED_WILL(opt))
791 TELOPT_UNANSWERED_WILL(opt) = 0;
792 if (cmd == DO && TELOPT_UNANSWERED_DONT(opt))
793 TELOPT_UNANSWERED_DONT(opt) = 0;
794 if (cmd == WILL && TELOPT_UNANSWERED_WONT(opt))
795 TELOPT_UNANSWERED_WONT(opt) = 0;
800 /* Send a telnet sub-option */
801 /* Returns 1 if command was sent, 0 if not, -1 on error */
804 tn_ssbopt(opt,sub,data,len) int opt, sub; CHAR * data; int len; {
808 if (ttnet != NET_TCPB) return(0); /* Must be TCP/IP */
809 if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
810 if (!TELOPT_OK(opt)) return(-1);
811 if (len < 0 || len > 250) {
812 debug(F111,"Unable to Send TELNET SB - data too long","len",len);
813 return(-1); /* Data too long */
816 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
827 buf[1] = (CHAR) (SB & 0xff);
828 buf[2] = (CHAR) (opt & 0xff);
829 buf[3] = (CHAR) (sub & 0xff);
830 if (data && len > 0) {
831 memcpy(&buf[4],data,len);
833 buf[4+len] = (CHAR) IAC;
834 buf[5+len] = (CHAR) SE;
837 if (tn_deb || debses || deblog) {
838 if (opt == TELOPT_START_TLS && sub == 1)
839 ckmakmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
840 TELOPT(opt)," FOLLOWS IAC SE",NULL);
841 else if (opt == TELOPT_TTYPE && sub == 1)
842 ckmakmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ", TELOPT(opt),
843 " SEND IAC SE",NULL);
844 else if (opt == TELOPT_TTYPE && sub == 0)
845 ckmakxmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",TELOPT(opt)," IS ",
846 (char *)data," IAC SE",NULL,NULL,NULL,NULL,NULL,NULL,NULL);
847 else if (opt == TELOPT_NEWENVIRON) {
849 ckmakmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
850 TELOPT(TELOPT_NEWENVIRON)," ",
851 sub == TELQUAL_SEND ? "SEND" :
852 sub == TELQUAL_IS ? "IS" :
853 sub == TELQUAL_INFO ?"INFO" : "UNKNOWN" );
854 for (i = 0, quote = 0; i < len; i++) {
856 sprintf(hexbuf,"%02x",data[i]); /* safe but ugly */
857 ckstrncat(tn_msg_out,hexbuf,TN_MSG_LEN);
861 case TEL_ENV_USERVAR:
862 ckstrncat(tn_msg_out," USERVAR ",TN_MSG_LEN);
865 ckstrncat(tn_msg_out," VAR ",TN_MSG_LEN);
868 ckstrncat(tn_msg_out," VALUE ",TN_MSG_LEN);
871 ckstrncat(tn_msg_out," ESC ",TN_MSG_LEN);
875 ckstrncat(tn_msg_out," IAC ",TN_MSG_LEN);
878 sprintf(hexbuf,"%c",data[i]); /* safe but ugly */
879 ckstrncat(tn_msg_out,hexbuf,TN_MSG_LEN);
883 ckstrncat(tn_msg_out," IAC SE",TN_MSG_LEN);
885 sprintf(hexbuf,"%02x",sub); /* safe but ugly */
886 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
887 "TELNET SENT SB ",TELOPT(opt),
891 NULL,NULL,NULL,NULL,NULL,NULL,NULL
897 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
900 debug(F101,tn_msg_out,"",opt);
901 if (tn_deb || debses)
902 tn_debug(tn_msg_out);
904 rc = (ttol(buf,6+len) < 6+len);
906 ReleaseTelnetMutex();
915 tn_flui() -- Processes all waiting data for Telnet commands.
916 All non-Telnet data is to be stored into the Telnet Wait Buffer.
917 Returns 1 on success.
924 /* if (!IS_TELNET()) return(0); */
926 /* Wait up to 5 sec for responses to outstanding telnet negotiations */
927 while (x >= 0 && ttchk() > 0 && tn_wait_idx < TN_WAIT_BUF_SZ) {
931 x = tn_doop((CHAR)(x & 0xff),inserver?ckxech:duplex,ttinc);
932 debug(F101,"tn_flui tn_doop","",x);
934 case 1: /* Turn on echoing */
939 case 2: /* Turn off echoing */
945 tn_wait_buf[tn_wait_idx++] = IAC;
947 case 4: /* IKS event */
954 tn_wait_buf[tn_wait_idx++] = x;
964 static char tmploc[256];
966 /* Must compute the DISPLAY string we are going to send to the host */
967 /* If one is not assigned, do not send a string unless the user has */
968 /* explicitedly requested we try to send one via X-Display Location */
969 /* But do not send a string at all if FORWARD_X is in use. */
971 /* if (!IS_TELNET()) return(0); */
973 debug(F110,"tn_get_display() myipaddr",myipaddr,0);
974 #ifdef CK_ENVIRONMENT
975 debug(F110,"tn_get_display() tn_env_disp",tn_env_disp,0);
976 if (tn_env_disp[0]) {
977 int colon = ckindex(":",tn_env_disp,0,0,1);
979 ckmakmsg(tmploc,256,myipaddr,":",tn_env_disp,NULL);
981 } else if ( ckindex("localhost:",tn_env_disp,0,0,0) ||
982 ckindex("unix:",tn_env_disp,0,0,0) ||
983 ckindex("127.0.0.1:",tn_env_disp,0,0,0) ||
984 !ckstrcmp("0:",tn_env_disp,2,1) ||
985 tn_env_disp[0] == ':' ) {
986 ckmakmsg(tmploc,256,myipaddr,":",&tn_env_disp[colon],NULL);
992 #endif /* CK_ENVIRONMENT */
993 if (TELOPT_ME(TELOPT_XDISPLOC) ||
994 TELOPT_U(TELOPT_FORWARD_X)) {
995 ckmakmsg(tmploc,256,myipaddr,":0.0",NULL,NULL);
998 debug(F110,"tn_get_display() returns",disp,0);
999 return((CHAR *)disp);
1003 static Xauth fake_xauth = {0,0,NULL,0,NULL,0,NULL,0,NULL};
1004 static Xauth *real_xauth=NULL;
1007 * Author: Jim Fulton, MIT X Consortium
1009 * fwdx_parse_displayname -
1010 * display a display string up into its component parts
1013 #define UNIX_CONNECTION "unix"
1014 #define UNIX_CONNECTION_LENGTH 4
1018 * private utility routines
1023 XmuGetHostname (char *buf, int maxlen)
1025 XmuGetHostname (buf, maxlen)
1028 #endif /* CK_ANSIC */
1034 * same host name crock as in server and xinit.
1036 struct utsname name;
1039 len = strlen (name.nodename);
1040 if (len >= maxlen) len = maxlen - 1;
1041 strncpy (buf, name.nodename, len);
1045 (void) gethostname (buf, maxlen);
1046 buf [maxlen - 1] = '\0';
1054 copystring (char *src, int len)
1056 copystring (src, len)
1059 #endif /* CK_ANSIC */
1063 if (!src && len != 0) return NULL;
1064 cp = malloc (len + 1);
1066 if (src) strncpy (cp, src, len);
1074 get_local_hostname (char *buf, int maxlen)
1076 get_local_hostname (buf, maxlen)
1082 (void) XmuGetHostname (buf, maxlen);
1083 return (buf[0] ? buf : NULL);
1092 return (get_local_hostname (buf, sizeof buf) ?
1093 copystring (buf, strlen (buf)) : NULL);
1100 fwdx_parse_displayname (char *displayname, int *familyp, char **hostp,
1101 int *dpynump, int *scrnump, char **restp)
1103 fwdx_parse_displayname (displayname, familyp, hostp, dpynump, scrnump, restp)
1105 int *familyp; /* return */
1106 char **hostp; /* return */
1107 int *dpynump, *scrnump; /* return */
1108 char **restp; /* return */
1109 #endif /* CK_ANSIC */
1111 char *ptr; /* work variables */
1112 int len; /* work variable */
1113 int family = -1; /* value to be returned */
1114 char *host = NULL; /* must free if set and error return */
1115 int dpynum = -1; /* value to be returned */
1116 int scrnum = 0; /* value to be returned */
1117 char *rest = NULL; /* must free if set and error return */
1118 int dnet = 0; /* if 1 then using DECnet */
1120 /* check the name */
1121 if (!displayname || !displayname[0])
1123 /* must have at least :number */
1124 ptr = (char *)strchr(displayname, ':');
1125 if (!ptr || !ptr[1]) return 0;
1126 if (ptr[1] == ':') {
1127 if (ptr[2] == '\0') return 0;
1132 * get the host string; if none is given, use the most effiecient path
1135 len = (ptr - displayname); /* length of host name */
1136 if (len == 0) { /* choose most efficient path */
1138 host = copystring (UNIX_CONNECTION, UNIX_CONNECTION_LENGTH);
1139 family = FamilyLocal;
1142 host = copystring ("0", 1);
1143 family = FamilyDECnet;
1145 host = copyhostname ();
1146 family = FamilyInternet;
1150 host = copystring (displayname, len);
1155 if (host && strcmp (host, UNIX_CONNECTION) == 0)
1156 family = FamilyLocal;
1159 family = FamilyInternet;
1163 if (!host) return 0;
1167 * get the display number; we know that there is something after the
1168 * colon (or colons) from above. note that host is now set and must
1169 * be freed if there is an error.
1172 if (dnet) ptr++; /* skip the extra DECnet colon */
1173 ptr++; /* move to start of display num */
1177 for (cp = ptr; *cp && isascii(*cp) && isdigit(*cp); cp++) ;
1179 /* check present and valid follow */
1180 if (len == 0 || (*cp && *cp != '.')) {
1185 dpynum = atoi (ptr); /* it will handle num. as well */
1190 * now get screen number if given; ptr may point to nul at this point
1192 if (ptr[0] == '.') {
1196 for (cp = ptr; *cp && isascii(*cp) && isdigit(*cp); cp++) ;
1198 if (len == 0 || (*cp && *cp != '.')) { /* all prop name */
1203 scrnum = atoi (ptr); /* it will handle num. as well */
1208 * and finally, get any additional stuff that might be following the
1209 * the screen number; ptr must point to a period if there is anything
1212 if (ptr[0] == '.') {
1216 rest = copystring (ptr, len);
1248 fwdx_tn_sb( unsigned char * sb, int n )
1250 fwdx_tn_sb( sb, n ) unsigned char * sb; int n;
1251 #endif /* CK_ANSIC */
1253 unsigned short hchannel, nchannel;
1258 /* check to ensure we have negotiated Forward X */
1259 if ( sstelnet && !TELOPT_ME(TELOPT_FORWARD_X) ||
1260 !sstelnet && !TELOPT_U(TELOPT_FORWARD_X) ) {
1261 debug(F100,"fwdx_tn_sb() not negotiated","",0);
1266 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1273 if (sstelnet && n == 4)
1274 rc = fwdx_create_listen_socket(sb[1]);
1277 if ( !sstelnet && n >= 5 ) {
1278 p = (unsigned char *) &nchannel;
1280 /* IAC quoting has been stripped in tn_sb() */
1283 hchannel = ntohs(nchannel);
1284 rc = fwdx_open_client_channel(hchannel);
1286 /* Failed; Send CLOSE channel */
1287 fwdx_send_close(hchannel);
1288 rc = 0; /* Do not consider this to be a telnet error */
1291 if ( !TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started ) {
1292 ckThreadBegin( &fwdx_thread,32655, 0, FALSE, 0 ) ;
1293 TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 1;
1299 p = (unsigned char *) &nchannel;
1301 /* IAC quoting has been stripped in tn_sb() */
1304 hchannel = ntohs(nchannel);
1305 fwdx_close_channel(hchannel);
1306 rc = 0; /* no errors when closing */
1309 p = (unsigned char *) &nchannel;
1311 /* IAC quoting has been stripped in tn_sb() */
1314 hchannel = ntohs(nchannel);
1315 rc = fwdx_send_xauth_to_xserver(hchannel,(CHAR *)&sb[3],n-5);
1316 if ( rc >= 0 && n-5-rc > 0) {
1317 rc = fwdx_write_data_to_channel(hchannel,(char *)&sb[3+rc],n-5-rc);
1319 /* Failed; Send CLOSE channel */
1320 rc = fwdx_send_close(hchannel);
1329 rc = fwdx_server_accept_options((char*)&sb[2],n-3);
1332 rc = fwdx_client_reply_options((char *)&sb[2],n-3);
1341 rc = 0; /* we don't recognize, not an error */
1348 p = (unsigned char *) &nchannel;
1350 /* IAC quoting has been stripped in tn_sb() */
1353 hchannel = ntohs(nchannel);
1354 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[hchannel].suspend =
1355 (sb[0] == FWDX_XOFF);
1360 return(rc < 0 ? -1 : 0);
1365 fwdx_send_xauth_to_xserver(int channel, unsigned char * data, int len)
1367 fwdx_send_xauth_to_xserver(channel, data, len)
1368 int channel; unsigned char * data; int len;
1369 #endif /* CK_ANSIC */
1371 int name_len, data_len, i;
1373 for (i = 0; i < MAXFWDX ; i++) {
1374 if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id == channel)
1380 if (!TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth)
1386 /* Parse the lengths of variable-length fields. */
1387 if (data[0] == 0x42) { /* byte order MSB first. */
1388 /* Xauth packets appear to always have this format */
1389 if ( data[1] != 0x00 ||
1396 name_len = (data[6] << 8) + data[7];
1397 data_len = (data[8] << 8) + data[9];
1398 } else if (data[0] == 0x6c) { /* Byte order LSB first. */
1399 /* Xauth packets appear to always have this format */
1400 if ( data[1] != 0x00 ||
1407 name_len = data[6] + (data[7] << 8);
1408 data_len = data[8] + (data[9] << 8);
1410 /* bad byte order byte */
1414 /* Check if the whole packet is in buffer. */
1415 if (len < 12 + ((name_len + 3) & ~3) + ((data_len + 3) & ~3))
1417 /* If the Telnet Server allows a real Xauth message to be sent */
1418 /* Then let the message be processed by the Xserver. */
1419 if (name_len + data_len > 0) {
1420 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
1424 /* If an empty Xauth message was received. We are going to */
1425 /* send our own Xauth message using the real Xauth data. And */
1426 /* then send any other data in the buffer. */
1428 int c, err, dpynum, scrnum, family, sb_len;
1429 char *display, *host = NULL, *rest = NULL;
1430 unsigned char *sb, *p;
1432 /* parse the local DISPLAY env var */
1433 display = getenv("DISPLAY");
1435 display = "127.0.0.1:0.0";
1437 if (fwdx_parse_displayname(display,
1438 &family, &host, &dpynum, &scrnum, &rest)) {
1439 char * disp_no = ckitoa(dpynum); /* should be unsigned */
1440 if (family == FamilyLocal) {
1441 /* call with address = "<local host name>" */
1442 char address[300] = "localhost";
1443 gethostname(address, sizeof(address) - 1);
1444 real_xauth = XauGetAuthByAddr(family,
1450 else if (family == FamilyInternet) {
1451 /* call with address = 4 bytes numeric ip addr (MSB) */
1453 if (hi = gethostbyname(host))
1454 real_xauth = XauGetAuthByAddr(family, 4,
1455 hi->h_addr, strlen(disp_no),
1459 if (host) free(host);
1460 if (rest) free(rest);
1462 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
1466 if (!strncmp(real_xauth->name,
1467 "MIT-MAGIC-COOKIE-1",
1468 real_xauth->name_length)) {
1471 name_len = real_xauth->name_length;
1474 if ( data[0] == 0x42 ) {
1475 msg[0] = 0x42; /* MSB order */
1476 msg[1] = msg[2] = 0;
1478 msg[4] = msg[5] = 0;
1479 msg[6] = (name_len >> 8);
1480 msg[7] = (name_len & 0xFF);
1481 msg[8] = (data_len >> 8);
1482 msg[9] = (data_len & 0xFF);
1484 msg[0] = 0x6c; /* LSB order */
1487 msg[3] = msg[4] = msg[5] = 0;
1488 msg[6] = (name_len & 0xFF);
1489 msg[7] = (name_len >> 8);
1490 msg[8] = (data_len & 0xFF);
1491 msg[9] = (data_len >> 8);
1493 msg[10] = msg[11] = 0;
1494 memcpy(&msg[12],real_xauth->name,18);
1495 msg[30] = msg[31] = 0;
1496 memcpy(&msg[32],real_xauth->data,16);
1498 if (fwdx_write_data_to_channel(channel,(char *)msg,48) < 0) {
1499 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
1502 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
1506 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
1507 return(0); /* we do not know how to handle this type yet */
1512 debug(F100,"fwdx_send_xauth_to_xserver error","",0);
1520 fwdx_authorize_channel(int channel, unsigned char * data, int len)
1522 fwdx_authorize_channel(channel, data, len)
1523 int channel; unsigned char * data; int len;
1524 #endif /* CK_ANSIC */
1526 /* XXX maybe we should have some retry handling if not the whole first
1527 * authorization packet arrives complete
1529 if ( !TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[channel].authorized ) {
1530 int name_len, data_len;
1535 /* Parse the lengths of variable-length fields. */
1536 if (data[0] == 0x42) { /* byte order MSB first. */
1537 /* Xauth packets appear to always have this format */
1538 if ( data[1] != 0x00 ||
1545 name_len = (data[6] << 8) + data[7];
1546 data_len = (data[8] << 8) + data[9];
1547 } else if (data[0] == 0x6c) { /* Byte order LSB first. */
1548 /* Xauth packets appear to always have this format */
1549 if ( data[1] != 0x00 ||
1556 name_len = data[6] + (data[7] << 8);
1557 data_len = data[8] + (data[9] << 8);
1559 /* bad byte order byte */
1562 /* Check if authentication protocol matches. */
1563 if (name_len != fake_xauth.name_length ||
1564 memcmp(data + 12, fake_xauth.name, name_len) != 0) {
1565 /* connection uses different authentication protocol */
1568 /* Check if authentication data matches our fake data. */
1569 if (data_len != fake_xauth.data_length ||
1570 memcmp(data + 12 + ((name_len + 3) & ~3),
1571 fake_xauth.data, fake_xauth.data_length) != 0) {
1572 /* auth data does not match fake data */
1575 /* substitute the fake data with real data if we have any */
1576 if (real_xauth && real_xauth->data)
1577 memcpy(data + 12 + ((name_len + 3) & ~3),
1578 real_xauth->data, data_len);
1580 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[channel].authorized = 1;
1586 #endif /* COMMENT */
1590 fwdx_send_close(int channel)
1592 fwdx_send_close(channel) int channel;
1593 #endif /* CK_ANSIC */
1595 unsigned short nchannel;
1600 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1605 nchannel = htons(channel);
1606 p = (unsigned char *) &nchannel;
1609 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
1610 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
1611 sb_out[i++] = TELOPT_FORWARD_X; /* Forward X */
1612 sb_out[i++] = FWDX_CLOSE; /* Open */
1613 sb_out[i++] = p[0]; /* First Byte of Channel */
1616 sb_out[i++] = p[1]; /* Second Byte of Channel */
1619 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
1620 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
1622 if (deblog || tn_deb || debses) {
1623 ckmakxmsg((char *)fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
1624 TELOPT(TELOPT_FORWARD_X),
1625 " CLOSE CHANNEL=",ckitoa(channel)," IAC SE",
1626 NULL,NULL,NULL,NULL,NULL,NULL,NULL
1631 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1634 debug(F100,(char *)fwdx_msg_out,"",0);
1635 if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
1637 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
1639 ReleaseTelnetMutex();
1648 fwdx_send_open(int channel)
1649 #else /* CK_ANSIC */
1650 fwdx_send_open(channel) int channel;
1651 #endif /* CK_ANSIC */
1653 unsigned short nchannel;
1658 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1663 nchannel = htons(channel);
1664 p = (unsigned char *) &nchannel;
1667 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
1668 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
1669 sb_out[i++] = TELOPT_FORWARD_X; /* Forward X */
1670 sb_out[i++] = FWDX_OPEN; /* Open */
1671 sb_out[i++] = p[0]; /* First Byte of Channel */
1674 sb_out[i++] = p[1]; /* Second Byte of Channel */
1677 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
1678 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
1680 if (deblog || tn_deb || debses) {
1681 ckmakxmsg((char *)fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
1682 TELOPT(TELOPT_FORWARD_X),
1683 " OPEN CHANNEL=",ckitoa(channel)," IAC SE",
1684 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
1688 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1691 debug(F100,(char *)fwdx_msg_out,"",0);
1692 if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
1694 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
1696 ReleaseTelnetMutex();
1705 fwdx_client_reply_options(char *opts, int n)
1707 fwdx_client_reply_options(opts, n) char *opts; int n;
1708 #endif /* CK_ANSIC */
1713 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1719 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
1720 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
1721 sb_out[i++] = TELOPT_FORWARD_X; /* Forward X */
1722 sb_out[i++] = FWDX_OPTIONS; /* Options */
1724 /* Look for the options we recognize and will support for this session */
1725 /* and reply with their bytes set */
1726 for (j=0; j<n; j++,i++) {
1727 sb_out[i] = FWDX_OPT_NONE; /* Add zero byte - no options */
1729 /* If we had any options to support, this is how we would do it */
1731 if (opts[j] & FWDX_OPT_XXXX) {
1732 /* set flag to remember option is in use */
1734 sb_out[i] |= FWDX_OPT_XXXX;
1737 #endif /* COMMENT */
1739 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
1740 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
1742 if (deblog || tn_deb || debses) {
1743 ckmakxmsg((char *)fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
1744 TELOPT(TELOPT_FORWARD_X),
1745 " OPTIONS ",ckctox(sb_out[4],1)," IAC SE",
1746 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
1750 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1753 debug(F100,(char *)fwdx_msg_out,"",0);
1754 if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
1756 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
1758 ReleaseTelnetMutex();
1767 fwdx_send_options() {
1771 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1777 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
1778 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
1779 sb_out[i++] = TELOPT_FORWARD_X; /* Forward X */
1780 sb_out[i++] = FWDX_OPTIONS; /* Options */
1781 sb_out[i] = FWDX_OPT_NONE;
1782 /* activate options here */
1784 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
1785 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
1788 if (deblog || tn_deb || debses) {
1789 ckmakmsg((char *)fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
1790 TELOPT(TELOPT_FORWARD_X),
1791 " OPTIONS 00 IAC SE",NULL);
1795 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1798 debug(F100,(char *)fwdx_msg_out,"",0);
1799 if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
1801 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
1803 ReleaseTelnetMutex();
1812 fwdx_send_data_from_channel(int channel, char * data, int len)
1814 fwdx_send_data_from_channel(channel, data, len)
1815 int channel; char * data; int len;
1818 unsigned short nchannel;
1819 /* static */ CHAR sb_priv[2048];
1821 int i, j, j_sav, rc;
1824 debug(F111,"fwdx_send_data_from_channel()","channel",channel);
1827 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1832 nchannel = htons(channel);
1833 p = (unsigned char *) &nchannel;
1836 sb_priv[j++] = (CHAR) IAC; /* I Am a Command */
1837 sb_priv[j++] = (CHAR) SB; /* Subnegotiation */
1838 sb_priv[j++] = TELOPT_FORWARD_X; /* Forward X */
1839 sb_priv[j++] = FWDX_DATA; /* Data */
1840 sb_priv[j++] = p[0]; /* First Byte of Channel */
1843 sb_priv[j++] = p[1]; /* Second Byte of Channel */
1848 for (i = 0; i < len; i++) {
1849 tmp = (unsigned int)data[i];
1856 if ( j >= 2045 && (i < len-1) ) {
1857 sb_priv[j++] = (CHAR) IAC; /* End of Subnegotiation */
1858 sb_priv[j++] = (CHAR) SE; /* marked by IAC SE */
1861 if (deblog || tn_deb || debses) {
1862 ckmakxmsg( (char *)fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
1863 TELOPT(TELOPT_FORWARD_X),
1864 " DATA CHANNEL=",ckitoa(channel)," ",
1865 NULL,NULL,NULL,NULL,NULL,NULL,NULL );
1866 tn_hex((CHAR *)fwdx_msg_out,
1867 TN_MSG_LEN,&sb_priv[j_sav],j-(j_sav+2));
1868 ckstrncat((char *)fwdx_msg_out," IAC SE",TN_MSG_LEN);
1872 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1875 debug(F100,(char *)fwdx_msg_out,"",0);
1876 if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
1878 rc = (ttol(sb_priv,j) < 0); /* Send it. */
1880 ReleaseTelnetMutex();
1883 debug(F110,"fwdx_send_data_from_channel()","ttol() failed",0);
1888 sb_priv[j++] = (CHAR) IAC; /* I Am a Command */
1889 sb_priv[j++] = (CHAR) SB; /* Subnegotiation */
1890 sb_priv[j++] = TELOPT_FORWARD_X; /* Forward X */
1891 sb_priv[j++] = FWDX_DATA; /* Data */
1892 sb_priv[j++] = p[0]; /* First Byte of Channel */
1895 sb_priv[j++] = p[1]; /* Second Byte of Channel */
1901 sb_priv[j++] = (CHAR) IAC; /* End of Subnegotiation */
1902 sb_priv[j++] = (CHAR) SE; /* marked by IAC SE */
1905 if (deblog || tn_deb || debses) {
1906 ckmakxmsg( (char *)fwdx_msg_out,TN_MSG_LEN,
1907 "TELNET SENT SB ",TELOPT(TELOPT_FORWARD_X),
1908 " DATA ",ckctox(p[0],1)," ",ckctox(p[1],1)," ",
1909 NULL,NULL,NULL,NULL,NULL);
1910 tn_hex((CHAR *)fwdx_msg_out,TN_MSG_LEN,&sb_priv[6],j-8);
1911 ckstrncat((char *)fwdx_msg_out," IAC SE",TN_MSG_LEN);
1915 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1918 debug(F100,(char *)fwdx_msg_out,"",0);
1919 if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
1921 rc = (ttol(sb_priv,j) < 0); /* Send it. */
1923 ReleaseTelnetMutex();
1926 debug(F110,"fwdx_send_data_from_channel()","ttol() failed",0);
1934 static unsigned char *
1936 fwdx_add_quoted_twobyte(unsigned char *p, unsigned short twobyte)
1938 fwdx_add_quoted_twobyte(p, twobyte)
1939 unsigned char *p; unsigned short twobyte;
1940 #endif /* CK_ANSIC */
1941 /* adds the IAC quoted (MSB) representation of 'channel' at buffer pointer 'p',
1942 * returning pointer to new buffer position. NO OVERFLOW CHECK!
1945 *p++ = (unsigned char)((twobyte >> 8) & 0xFF);
1946 if (*(p - 1) == 0xFF)
1948 *p++ = (unsigned char)(twobyte & 0xFF);
1949 if (*(p - 1) == 0xFF)
1956 fwdx_create_fake_xauth(char *name, int name_len, int data_len)
1958 fwdx_create_fake_xauth(name, name_len, data_len)
1959 char *name; int name_len; int data_len;
1960 #endif /* CK_ANSIC */
1962 char stackdata[256];
1965 if (!name_len || !data_len)
1967 fake_xauth.name = malloc(name_len);
1968 fake_xauth.data = malloc(data_len);
1969 if (!fake_xauth.name || !fake_xauth.data)
1971 fake_xauth.name_length = name_len;
1972 memcpy(fake_xauth.name, name, name_len);
1973 fake_xauth.data_length = data_len;
1975 /* try to make a random unsigned int to feed srand() */
1978 for (n = 0; n < sizeof(stackdata); n++)
1980 srand((unsigned int)c);
1981 for (c = 0; c < data_len; c++)
1982 fake_xauth.data[c] = (unsigned char)rand();
1987 /* No longer used */
1989 fwdx_send_xauth(void)
1991 int c, err, dpynum, family, sb_len, rc;
1992 char *display, *host = NULL;
1993 unsigned char *sb_priv, *p;
1995 /* parse the local DISPLAY env var */
1996 if (!(display = tn_get_display()))
1998 if (fwdx_parse_displayname(display, &family, &host, &dpynum, NULL, NULL)) {
1999 char * disp_no = ckitoa(dpynum);
2000 if (family == FamilyLocal) {
2001 /* call with address = "<local host name>" */
2002 char address[300] = "localhost";
2003 gethostname(address, sizeof(address) - 1);
2004 real_xauth = XauGetAuthByAddr(family,
2011 else if (family == FamilyInternet) {
2012 /* call with address = 4 bytes numeric ip addr (MSB) */
2014 if (hi = gethostbyname(host))
2015 real_xauth = XauGetAuthByAddr(family, 4,
2027 err = fwdx_create_fake_xauth(real_xauth->name,
2028 real_xauth->name_length,
2029 real_xauth->data_length
2032 err = fwdx_create_fake_xauth("MIT-MAGIC-COOKIE-1",
2033 strlen("MIT-MAGIC-COOKIE-1"), 16);
2037 /* allocate memory for the SB block, alloc for worst case */
2038 /* the following sprintf() calls are safe due to length checking */
2039 /* buffer is twice as big as the input just in case every byte was IAC */
2040 sb_len = 5 + 2 + 2 + fake_xauth.name_length + fake_xauth.data_length + 2;
2041 if (!(sb_priv = malloc(2 * sb_len)))
2044 sprintf(p, "%c%c%c%c%c", IAC, SB, TELOPT_FORWARD_X,
2045 FWDX_OPT_DATA, FWDX_OPT_XAUTH);
2047 p = fwdx_add_quoted_twobyte(p, fake_xauth.name_length);
2048 p = fwdx_add_quoted_twobyte(p, fake_xauth.data_length);
2049 for (c = 0; c < fake_xauth.name_length; c++) {
2050 *p++ = fake_xauth.name[c];
2051 if ((unsigned char)fake_xauth.name[c] == 0xFF)
2054 for (c = 0; c < fake_xauth.data_length; c++) {
2055 *p++ = fake_xauth.data[c];
2056 if ((unsigned char)fake_xauth.data[c] == 0xFF)
2059 sprintf(p, "%c%c", IAC, SE);
2063 if (deblog || tn_deb || debses) {
2064 sprintf((char *)fwdx_msg_out,"TELNET SENT SB %s OPTION_DATA XAUTH ",
2065 TELOPT(TELOPT_FORWARD_X));
2066 tn_hex((char *)fwdx_msg_out,TN_MSG_LEN,&sb_priv[5],(p-sb_priv)-7);
2067 ckstrncat((char *)fwdx_msg_out," IAC SE",TN_MSG_LEN);
2071 /* Add Telnet Debug info here */
2073 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
2076 debug(F100,(char *)fwdx_msg_out,"",0);
2077 if (tn_deb || debses) tn_debug((char *)fwdx_msg_out);
2079 rc = ( ttol(sb_priv,p-sb_priv) < 0 ); /* Send it. */
2081 ReleaseTelnetMutex();
2084 debug(F110,"fwdx_send_xauth()","ttol() failed",0);
2092 #endif /* COMMENT */
2094 /* Only if we ever become a server - not yet ported to Kermit */
2095 /* And even so most of this code does not belong in this module */
2098 fwdx_write_xauthfile(void)
2100 int dpynum, scrnum, family;
2101 char myhost[300], *host, *rest = NULL;
2103 struct sockaddr_in saddr;
2106 if (!fwdx_display && !fwdx_xauthfile)
2108 if (!parse_displayname(fwdx_display,
2109 &family, &host, &dpynum, &scrnum, &rest))
2111 if (rest) free(rest);
2112 if (host) free(host);
2113 if (family != FamilyInternet)
2114 return 3; /* every thing but FamilyInternet is unexpected */
2116 /* X connections to localhost:1 is actually treated as local unix sockets,
2117 * see the 'xauth' man page.
2119 xauth.family = FamilyLocal;
2120 if (gethostname(myhost, sizeof(myhost) - 1))
2122 xauth.address_length = strlen(myhost);
2123 if (!(xauth.address = malloc(xauth.address_length)))
2125 memcpy(xauth.address, myhost, xauth.address_length);
2127 /* the display number is written as a string, not numeric */
2128 if (!(xauth.number = malloc(6)))
2130 snprintf(xauth.number, 5, "%u", dpynum);
2131 xauth.number_length = strlen(xauth.number);
2132 if (!(file = fopen(fwdx_xauthfile, "wb")))
2134 if (!XauWriteAuth(file, &xauth))
2137 setenv("XAUTHORITY", fwdx_xauthfile, 1);
2142 fwdx_setup_xauth(unsigned char *sp, int len)
2143 /* called with 'len' xauth bytes, starting at 'sp'
2144 * the data format is: <uint16 name_length> <uint16 data_length> <name> <data>
2149 if (!fwdx_options[FWDX_OPT_XAUTH])
2154 /* setup the xauth struct */
2155 xauth.name_length = (sp[0] << 8) + sp[1];
2156 xauth.data_length = (sp[2] << 8) + sp[3];
2157 if (len != 4 + xauth.name_length + xauth.data_length)
2159 xauth.name = malloc(xauth.name_length);
2160 xauth.data = malloc(xauth.data_length);
2161 if (!xauth.name || !xauth.data)
2163 memcpy(xauth.name, sp + 4, xauth.name_length);
2164 memcpy(xauth.data, sp + 4 + xauth.name_length, xauth.data_length);
2166 /* Setup to always have a local .Xauthority. */
2167 fwdx_xauthfile = malloc(MAXPATHLEN+1);
2168 snprintf(fwdx_xauthfile, MAXPATHLEN, "/tmp/XauthXXXXXX");
2169 if ((xauthfd = mkstemp(fwdx_xauthfile)) != -1)
2170 /* we change file ownership later, when we know who is to be owner! */
2173 free(fwdx_xauthfile);
2174 fwdx_xauthfile = NULL;
2177 /* Must have the subshell's new DISPLAY env var to write xauth to xauthfile */
2179 if (fwdx_write_xauthfile())
2185 void fwdx_set_xauthfile_owner(int uid)
2189 if (!fwdx_xauthfile || !(pwd = getpwuid(uid)))
2191 chown(fwdx_xauthfile, pwd->pw_uid, pwd->pw_gid);
2195 fwdx_server_accept_options(unsigned char *sp, int len)
2196 /* called with 'len' option bytes, starting at 'sp' */
2200 for (c = 0; c < len-2; c++) {
2202 if (sp[c] & FWDX_OPT_XAUTH)
2208 #endif /* FWDX_SERVER */
2209 #endif /* CK_FORWARD_X */
2213 iks_wait() -- Wait for an IKS subnegotiation response.
2214 sb - is either KERMIT_REQ_START or KERMIT_REQ_STOP depending on the desired
2215 state of the peer's Kermit server.
2216 flushok - specifies whether it is ok to throw away non-Telnet data
2217 if so, then we call ttflui() instead of tn_flui().
2219 1 if the desired state is achieved or if it is unknown.
2220 0 if the desired state is not achieved.
2224 iks_wait(int sb, int flushok)
2225 #else /* CK_ANSIC */
2226 iks_wait(sb,flushok) int sb; int flushok;
2227 #endif /* CK_ANSIC */
2229 int tn_wait_save = tn_wait_flg;
2232 if (TELOPT_U(TELOPT_KERMIT)) {
2234 case KERMIT_REQ_START:
2236 "iks_wait KERMIT_REQ_START",
2238 TELOPT_SB(TELOPT_KERMIT).kermit.u_start
2240 tn_siks(KERMIT_REQ_START);
2241 tn_wait_flg = 1; /* Kermit Option MUST wait */
2245 x = tn_wait("iks_wait() me_iks_req_start");
2246 } while (x == 0 && flushok && tn_wait_idx == TN_WAIT_BUF_SZ);
2247 tn_wait_flg = tn_wait_save;
2250 if (tn_wait_idx == TN_WAIT_BUF_SZ) {
2252 * We are attempting to start a kermit server on the peer
2253 * the most likely reason is because we want to perform a
2254 * file transfer. But there is a huge amount of non telnet
2255 * negotiation data coming in and so we have not been able
2256 * to find the response. So we will lie and assume that
2257 * response is 'yes'. The worse that will happen is that
2258 * a RESP_STOP is received after we enter protocol mode.
2259 * And the protocol operation will be canceled.
2265 return(TELOPT_SB(TELOPT_KERMIT).kermit.u_start);
2267 case KERMIT_REQ_STOP:
2269 "iks_wait KERMIT_REQ_STOP",
2271 TELOPT_SB(TELOPT_KERMIT).kermit.u_start
2273 tn_siks(KERMIT_REQ_STOP);
2274 tn_wait_flg = 1; /* Kermit Option MUST wait */
2278 x = tn_wait("iks_wait() me_iks_req_stop");
2279 } while (x == 0 && flushok && tn_wait_idx == TN_WAIT_BUF_SZ);
2280 tn_wait_flg = tn_wait_save;
2284 if (tn_wait_idx == TN_WAIT_BUF_SZ) {
2286 * We are attempting to stop a kermit server on the peer
2287 * the most likely reason being that we want to enter
2288 * CONNECT mode. But there is a huge amount of non telnet
2289 * negotiation data coming in and so we have not been able
2290 * to find the response. So we will lie and assume that
2291 * the answer is 'yes' and allow the CONNECT command to
2292 * succeed. The worst that happens is that CONNECT mode
2293 * swallows the incoming data displaying it to the user
2294 * and then it resumes Kermit client mode.
2300 return(!TELOPT_SB(TELOPT_KERMIT).kermit.u_start);
2310 iks_tn_sb(CHAR * sb, int n)
2312 iks_tn_sb(sb, n) CHAR * sb; int n;
2313 #endif /* CK_ANSIC */
2319 int inautodl = 0, cmdadl = 1;
2322 extern int autodl, inautodl, cmdadl;
2323 #endif /* CK_AUTODL */
2326 case KERMIT_START: /* START */
2327 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 1;
2330 case KERMIT_STOP: /* STOP */
2331 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
2334 case KERMIT_REQ_START: /* REQ-START */
2338 cmdadl = 1; /* Turn on packet detection */
2339 #endif /* CK_AUTODL */
2340 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
2341 tn_siks(KERMIT_RESP_START);
2342 } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
2343 tn_siks(KERMIT_RESP_START);
2348 if (local && (IsConnectMode() && autodl) ||
2349 (!IsConnectMode() &&
2350 (inautodl || sstate == 'x' || sstate == 'v'))
2352 tn_siks(KERMIT_RESP_START); /* START */
2356 if ((local && what == W_CONNECT && autodl) ||
2357 (local && what != W_CONNECT &&
2358 (inautodl || sstate == 'x' || sstate == 'v')
2360 tn_siks(KERMIT_RESP_START); /* START */
2363 #endif /* CK_AUTODL */
2364 #endif /* IKSDONLY */
2365 tn_siks(KERMIT_RESP_STOP);
2368 tn_siks(KERMIT_RESP_STOP);
2372 case KERMIT_REQ_STOP: /* REQ-STOP */
2373 /* The protocol requires that the request be responded to */
2374 /* either by changing states or by reporting the current */
2377 /* We need to provide the user some way of dictating what */
2378 /* the policies should be. For instance, if we are in */
2379 /* CONNECT mode with autodownload ON and we get a REQ-STOP*/
2380 /* what should the proper response be? */
2385 #endif /* CK_AUTODL */
2388 cmdadl = 0; /* Turn off packet detection */
2389 #endif /* CK_AUTODL */
2390 tn_siks(KERMIT_RESP_STOP);
2391 } else if (server) {
2393 if (en_fin) { /* If the server is allowed to stop */
2394 tn_siks(KERMIT_RESP_STOP);
2395 } else { /* We are not allowed to stop */
2396 tn_siks(KERMIT_RESP_START);
2402 else if (local && (IsConnectMode() && autodl) ||
2403 (!IsConnectMode() && inautodl)
2405 /* If we are a pseudo-server and the other side requests */
2406 /* that we stop, tell then that we have even though we */
2407 /* have not. Otherwise, the other side might refuse to */
2408 /* enter SERVER mode. */
2410 tn_siks(KERMIT_RESP_STOP); /* STOP */
2413 else if ((local && what == W_CONNECT && autodl) ||
2414 (local && what != W_CONNECT && inautodl)
2416 /* If we are a pseudo-server and the other side requests */
2417 /* that we stop, tell then that we have even though we */
2418 /* have not. Otherwise, the other side might refuse to */
2419 /* enter SERVER mode. */
2421 tn_siks(KERMIT_RESP_STOP); /* STOP */
2424 #endif /* CK_AUTODL */
2425 #endif /* IKSDONLY */
2429 /* If we are not currently in any mode that accepts */
2430 /* Kermit packets then of course report that we are */
2431 /* not being a Kermit server. */
2433 tn_siks(KERMIT_RESP_STOP); /* STOP */
2437 case KERMIT_SOP: { /* SOP */
2439 extern CHAR stchr; /* Incoming SOP character */
2442 TELOPT_SB(TELOPT_KERMIT).kermit.sop = 1;
2446 case KERMIT_RESP_START: /* START */
2447 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 1;
2448 if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start) {
2449 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
2450 } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop) {
2451 /* If we have issued a request to stop a Kermit Server */
2452 /* and the response is Start, then we must report this */
2453 /* to the caller. */
2454 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
2458 case KERMIT_RESP_STOP: /* STOP */
2459 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
2460 if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start) {
2461 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
2462 /* If we have issued a request to start a Kermit Server */
2463 /* and the response is Stop, then we must report this */
2464 /* to the caller. */
2465 } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop) {
2466 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
2473 } /* switch (sb[0]) */
2475 #endif /* IKS_OPTION */
2477 /* Initialize telnet settings - set default values for ME and U modes */
2483 #endif /* CK_FORWARD_X */
2484 #ifdef CK_ENVIRONMENT
2487 for (i = 0; i < 8; i++) {
2488 tn_env_uservar[i][0] = NULL;
2489 tn_env_uservar[i][1] = NULL;
2492 #endif /* CK_ENVIRONMENT */
2494 /* initialize all options to refuse in both directions */
2495 for (opt = 0; opt < NTELOPTS; opt++) {
2498 TELOPT_UNANSWERED_WILL(opt) = 0;
2499 TELOPT_UNANSWERED_DO(opt) = 0;
2500 TELOPT_UNANSWERED_WONT(opt) = 0;
2501 TELOPT_UNANSWERED_DONT(opt) = 0;
2502 TELOPT_UNANSWERED_SB(opt) = 0;
2503 TELOPT_ME_MODE(opt) = TN_NG_RF;
2504 TELOPT_U_MODE(opt) = TN_NG_RF;
2505 TELOPT_DEF_S_ME_MODE(opt) = TN_NG_RF;
2506 TELOPT_DEF_S_U_MODE(opt) = TN_NG_RF;
2507 TELOPT_DEF_C_ME_MODE(opt) = TN_NG_RF;
2508 TELOPT_DEF_C_U_MODE(opt) = TN_NG_RF;
2509 for (cmd = 0; cmd < 4; cmd ++)
2510 tncnts[TELOPT_INDEX(opt)][cmd] = 0;
2513 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
2514 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
2515 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
2516 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
2517 TELOPT_SB(TELOPT_KERMIT).kermit.sop = 0;
2518 #endif /* IKS_OPTION */
2520 #ifdef CK_ENCRYPTION
2521 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
2522 #endif /* CK_ENCRYPTION */
2525 TELOPT_SB(TELOPT_NAWS).naws.x = 0;
2526 TELOPT_SB(TELOPT_NAWS).naws.y = 0;
2527 #endif /* CK_NAWS */
2530 TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 0;
2531 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 0;
2532 TELOPT_SB(TELOPT_START_TLS).start_tls.auth_request = 0;
2535 /* Now set the ones we want to accept to the proper values */
2536 TELOPT_DEF_S_ME_MODE(TELOPT_SGA) = TN_NG_RQ;
2537 TELOPT_DEF_S_U_MODE(TELOPT_SGA) = TN_NG_RQ;
2538 TELOPT_DEF_C_ME_MODE(TELOPT_SGA) = TN_NG_AC;
2539 TELOPT_DEF_C_U_MODE(TELOPT_SGA) = TN_NG_AC;
2541 TELOPT_DEF_S_ME_MODE(TELOPT_BINARY) = TN_NG_AC;
2542 TELOPT_DEF_S_U_MODE(TELOPT_BINARY) = TN_NG_AC;
2543 TELOPT_DEF_C_ME_MODE(TELOPT_BINARY) = TN_NG_AC;
2544 TELOPT_DEF_C_U_MODE(TELOPT_BINARY) = TN_NG_AC;
2546 TELOPT_DEF_S_ME_MODE(TELOPT_LOGOUT) = TN_NG_AC;
2547 TELOPT_DEF_S_U_MODE(TELOPT_LOGOUT) = TN_NG_AC;
2548 TELOPT_DEF_C_ME_MODE(TELOPT_LOGOUT) = TN_NG_AC;
2549 TELOPT_DEF_C_U_MODE(TELOPT_LOGOUT) = TN_NG_AC;
2552 TELOPT_DEF_S_ME_MODE(TELOPT_KERMIT) = TN_NG_RQ;
2553 TELOPT_DEF_S_U_MODE(TELOPT_KERMIT) = TN_NG_RQ;
2554 TELOPT_DEF_C_ME_MODE(TELOPT_KERMIT) = TN_NG_RQ;
2555 TELOPT_DEF_C_U_MODE(TELOPT_KERMIT) = TN_NG_RQ;
2556 #endif /* IKS_OPTION */
2558 #ifdef CK_ENCRYPTION
2559 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
2560 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
2561 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
2562 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
2563 #endif /* CK_ENCRYPTION */
2565 TELOPT_DEF_S_ME_MODE(TELOPT_ECHO) = TN_NG_RQ;
2569 TELOPT_DEF_S_U_MODE(TELOPT_TTYPE) = TN_NG_RQ;
2571 #ifdef CK_ENVIRONMENT
2572 TELOPT_DEF_S_U_MODE(TELOPT_NEWENVIRON) = TN_NG_RQ;
2573 #endif /* CK_ENVIRONMENT */
2575 #ifdef CK_AUTHENTICATION
2576 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
2577 #endif /* CK_AUTHENTICATION */
2580 if (ck_ssleay_is_installed()) {
2581 TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RQ;
2582 TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = TN_NG_AC;
2587 TELOPT_DEF_S_U_MODE(TELOPT_NAWS) = TN_NG_RQ;
2588 #endif /* CK_NAWS */
2590 TELOPT_DEF_C_U_MODE(TELOPT_ECHO) = TN_NG_AC;
2591 TELOPT_DEF_C_ME_MODE(TELOPT_TTYPE) = TN_NG_RQ;
2593 #ifdef CK_ENVIRONMENT
2594 TELOPT_DEF_C_ME_MODE(TELOPT_NEWENVIRON) = TN_NG_RQ;
2595 #endif /* CK_ENVIRONMENT */
2597 #ifdef CK_AUTHENTICATION
2598 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
2599 #endif /* CK_AUTHENTICATION */
2602 TELOPT_DEF_C_ME_MODE(TELOPT_NAWS) = TN_NG_RQ;
2603 #endif /* CK_NAWS */
2606 TELOPT_DEF_C_ME_MODE(TELOPT_SNDLOC) = TN_NG_RQ;
2607 #endif /* CK_SNDLOC */
2610 TELOPT_DEF_C_U_MODE(TELOPT_FORWARD_X) = TN_NG_AC;
2611 TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket = -1;
2612 for (x = 0; x < MAXFWDX; x++) {
2613 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd = -1;
2614 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].id = -1;
2615 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].need_to_send_xauth = 0;
2616 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].suspend = 0;
2618 #endif /* CK_FORWARD_X */
2621 TELOPT_DEF_C_ME_MODE(TELOPT_COMPORT) = TN_NG_RQ;
2622 #endif /* TN_COMPORT */
2624 /* Set the initial values for currently known mode */
2625 for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
2626 if (TELOPT_OK(opt)) {
2627 TELOPT_ME_MODE(opt) = sstelnet ?
2628 TELOPT_DEF_S_ME_MODE(opt) :
2629 TELOPT_DEF_C_ME_MODE(opt);
2630 TELOPT_U_MODE(opt) = sstelnet ?
2631 TELOPT_DEF_S_U_MODE(opt) :
2632 TELOPT_DEF_C_U_MODE(opt);
2639 /* Send Delayed Subnegotiations */
2643 /* if (!IS_TELNET()) return; */
2645 if (TELOPT_SB(TELOPT_TTYPE).term.need_to_send) {
2647 TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 0;
2649 #ifdef CK_ENVIRONMENT
2650 if (TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send &&
2651 TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
2652 tn_snenv((CHAR *)TELOPT_SB(TELOPT_NEWENVIRON).env.str,
2653 TELOPT_SB(TELOPT_NEWENVIRON).env.len);
2654 free(TELOPT_SB(TELOPT_NEWENVIRON).env.str);
2655 TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
2656 TELOPT_SB(TELOPT_NEWENVIRON).env.len=0;
2657 TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 0;
2660 if (TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send) {
2662 TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 0;
2664 #endif /* CK_XDISPLOC */
2665 #endif /* CK_ENVIRONMENT */
2667 if (TELOPT_SB(TELOPT_NAWS).naws.need_to_send) {
2669 TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 0;
2671 #endif /* CK_NAWS */
2673 if (TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send) {
2675 TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 0;
2677 #endif /* CK_SNDLOC */
2679 if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send) {
2681 fwdx_send_options();
2682 TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 0;
2684 #endif /* CK_FORWARD_X */
2686 if (TELOPT_SB(TELOPT_COMPORT).comport.need_to_send) {
2688 TELOPT_SB(TELOPT_COMPORT).comport.need_to_send = 0;
2690 #endif /* TN_COMPORT */
2698 /* if (!IS_TELNET()) return(1); */
2700 tn_wait_idx = 0; /* Clear the tn_push() buffer */
2701 tn_wait_tmo = TN_TIMEOUT; /* Reset wait timer stats */
2705 /* Reset the TELNET OPTIONS counts */
2706 for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
2707 if (TELOPT_OK(opt)) {
2710 TELOPT_UNANSWERED_WILL(opt) = 0;
2711 TELOPT_UNANSWERED_DO(opt) = 0;
2712 TELOPT_UNANSWERED_WONT(opt) = 0;
2713 TELOPT_UNANSWERED_DONT(opt) = 0;
2714 TELOPT_UNANSWERED_SB(opt) = 0;
2715 TELOPT_ME_MODE(opt) = sstelnet ?
2716 TELOPT_DEF_S_ME_MODE(opt) :
2717 TELOPT_DEF_C_ME_MODE(opt);
2718 TELOPT_U_MODE(opt) = sstelnet ?
2719 TELOPT_DEF_S_U_MODE(opt) :
2720 TELOPT_DEF_C_U_MODE(opt);
2724 switch (TELOPT_ME_MODE(opt)) {
2726 debug(F110,"tn_ini ME REFUSE ",TELOPT(opt),0);
2729 debug(F110,"tn_ini ME ACCEPT ",TELOPT(opt),0);
2732 debug(F110,"tn_ini ME REQUEST",TELOPT(opt),0);
2735 debug(F110,"tn_ini ME REQUIRE",TELOPT(opt),0);
2738 switch (TELOPT_U_MODE(opt)) {
2740 debug(F110,"tn_ini U REFUSE ",TELOPT(opt),0);
2743 debug(F110,"tn_ini U ACCEPT ",TELOPT(opt),0);
2746 debug(F110,"tn_ini U REQUEST",TELOPT(opt),0);
2749 debug(F110,"tn_ini U REQUIRE",TELOPT(opt),0);
2754 for (cmd = 0; cmd < 4; cmd ++)
2755 tncnts[TELOPT_INDEX(opt)][cmd] = 0;
2758 #ifdef CK_ENVIRONMENT
2760 TELOPT_ME_MODE(TELOPT_NEWENVIRON) = TN_NG_RF;
2761 TELOPT_U_MODE(TELOPT_NEWENVIRON) = TN_NG_RF;
2763 #endif /* CK_ENVIRONMENT */
2766 TELOPT_DEF_C_ME_MODE(TELOPT_SNDLOC) = TN_NG_RF;
2767 #endif /* CK_SNDLOC */
2769 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
2770 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
2771 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
2772 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
2773 TELOPT_SB(TELOPT_KERMIT).kermit.sop = 0;
2774 #endif /* IKS_OPTION */
2775 #ifdef CK_ENCRYPTION
2776 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
2777 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 0;
2778 #endif /* CK_ENCRYPTION */
2780 TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 0;
2781 TELOPT_SB(TELOPT_NAWS).naws.x = 0;
2782 TELOPT_SB(TELOPT_NAWS).naws.y = 0;
2783 #endif /* CK_NAWS */
2784 TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 0;
2785 TELOPT_SB(TELOPT_TTYPE).term.type[0] = '\0';
2786 #ifdef CK_ENVIRONMENT
2787 TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 0;
2789 TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
2790 else if (TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
2791 free(TELOPT_SB(TELOPT_NEWENVIRON).env.str);
2792 TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
2794 TELOPT_SB(TELOPT_NEWENVIRON).env.len=0;
2796 TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 0;
2797 #endif /* CK_XDISPLOC */
2798 #endif /* CK_ENVIRONMENT */
2800 TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 0;
2801 #endif /* CK_SNDLOC */
2803 TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 0;
2804 TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket = -1;
2805 for (x = 0; x < MAXFWDX; x++) {
2806 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd = -1;
2807 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].id = -1;
2808 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].need_to_send_xauth = 0;
2809 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].suspend = 0;
2811 /* Reset Xauth data */
2813 XauDisposeAuth(real_xauth);
2816 if ( fake_xauth.name )
2817 free(fake_xauth.name);
2818 if ( fake_xauth.data )
2819 free(fake_xauth.data);
2820 if ( fake_xauth.address )
2821 free(fake_xauth.address);
2822 if ( fake_xauth.number )
2823 free(fake_xauth.number);
2824 memset(&fake_xauth,0,sizeof(fake_xauth));
2826 TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 0;
2828 #endif /* CK_FORWARD_X */
2830 if (tls_only_flag || ssl_only_flag) {
2831 TELOPT_ME_MODE(TELOPT_START_TLS) = TN_NG_RF;
2832 TELOPT_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
2834 TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 0;
2835 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 0;
2836 TELOPT_SB(TELOPT_START_TLS).start_tls.auth_request = 0;
2839 #ifdef CK_ENCRYPTION
2840 if (!ck_crypt_is_installed()
2842 || tls_only_flag || ssl_only_flag
2845 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2846 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2848 #endif /* CK_ENCRYPTION */
2851 TELOPT_SB(TELOPT_COMPORT).comport.need_to_send = 0;
2852 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
2853 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms = 0;
2855 #endif /* TN_COMPORT */
2857 tn_first = 0; /* No longer the first time init */
2860 ttnum = -1; /* Reset TermType negotiation */
2871 /* if (!IS_TELNET()) return(0); */
2873 if (tn_init && tn_begun)
2877 debug(F111,"tn_start","sstelnet",sstelnet);
2880 oldplex = duplex; /* save old duplex value */
2881 duplex = 1; /* and set to half duplex for telnet */
2884 if (!TELOPT_ME(TELOPT_START_TLS) &&
2885 TELOPT_ME_MODE(TELOPT_START_TLS) >= TN_NG_RQ) {
2886 if (tn_sopt(WILL, TELOPT_START_TLS) < 0)
2888 TELOPT_UNANSWERED_WILL(TELOPT_START_TLS) = 1;
2891 if (!TELOPT_U(TELOPT_START_TLS) &&
2892 TELOPT_U_MODE(TELOPT_START_TLS) >= TN_NG_RQ) {
2893 if (tn_sopt(DO, TELOPT_START_TLS) < 0)
2895 TELOPT_UNANSWERED_DO(TELOPT_START_TLS) = 1;
2900 #ifdef CK_AUTHENTICATION
2901 debug(F110,"tn_ini() CK_AUTHENTICATION","",0);
2902 if (tn_init) /* tn_ini() might be called recursively */
2904 if (!TELOPT_ME(TELOPT_AUTHENTICATION) &&
2905 TELOPT_ME_MODE(TELOPT_AUTHENTICATION) >= TN_NG_RQ) {
2906 if (tn_sopt(WILL, TELOPT_AUTHENTICATION) < 0)
2908 TELOPT_UNANSWERED_WILL(TELOPT_AUTHENTICATION) = 1;
2911 if (!TELOPT_U(TELOPT_AUTHENTICATION) &&
2912 TELOPT_U_MODE(TELOPT_AUTHENTICATION) >= TN_NG_RQ) {
2913 if (tn_sopt(DO, TELOPT_AUTHENTICATION) < 0)
2915 TELOPT_UNANSWERED_DO(TELOPT_AUTHENTICATION) = 1;
2918 #ifdef CK_ENCRYPTION
2919 if (TELOPT_U_MODE(TELOPT_AUTHENTICATION) == TN_NG_RF &&
2920 TELOPT_ME_MODE(TELOPT_AUTHENTICATION) == TN_NG_RF) {
2921 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2922 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2924 #endif /* CK_ENCRYPTION */
2925 #endif /* CK_AUTHENTICATION */
2929 debug(F110,"tn_ini() CK_NAWS !NOLOCAL","",0);
2931 /* Console terminal screen rows and columns */
2936 VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0)
2938 debug(F101,"tn_ini tt_cols 1","",VscrnGetWidth(VTERM));
2940 if (VscrnGetWidth(VTERM) < 0 ||
2941 VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0) < 0) {
2942 ttgwsiz(); /* Try to find out */
2947 VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0)
2949 debug(F101,"tn_ini tt_cols 2","",VscrnGetWidth(VTERM));
2950 /* Now do we know? */
2951 if (VscrnGetWidth(VTERM) > 0 &&
2952 VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0) > 0) {
2953 if (!TELOPT_ME(TELOPT_NAWS) &&
2954 TELOPT_ME_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
2955 if (tn_sopt(WILL, TELOPT_NAWS) < 0)
2957 TELOPT_UNANSWERED_WILL(TELOPT_NAWS) = 1;
2962 debug(F101,"tn_ini tt_rows 1","",tt_rows);
2963 debug(F101,"tn_ini tt_cols 1","",tt_cols);
2964 if (tt_rows < 0 || tt_cols < 0) { /* Not known yet */
2965 ttgwsiz(); /* Try to find out */
2967 debug(F101,"tn_ini tt_rows 2","",tt_rows);
2968 debug(F101,"tn_ini tt_cols 2","",tt_cols);
2969 if (tt_rows > 0 && tt_cols > 0) { /* Now do we know? */
2970 if (!TELOPT_ME(TELOPT_NAWS) &&
2971 TELOPT_ME_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
2972 if (tn_sopt(WILL, TELOPT_NAWS) < 0)
2974 TELOPT_UNANSWERED_WILL(TELOPT_NAWS) = 1;
2980 #endif /* NOLOCAL */
2982 if (!TELOPT_U(TELOPT_NAWS) &&
2983 TELOPT_U_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
2984 if (tn_sopt(DO, TELOPT_NAWS) < 0)
2986 TELOPT_UNANSWERED_DO(TELOPT_NAWS) = 1;
2990 #endif /* CK_NAWS */
2992 if (!TELOPT_ME(TELOPT_SGA) &&
2993 TELOPT_ME_MODE(TELOPT_SGA) >= TN_NG_RQ) {
2994 if (tn_sopt(WILL, TELOPT_SGA) < 0)
2996 TELOPT_UNANSWERED_WILL(TELOPT_SGA) = 1;
2999 if (!TELOPT_U(TELOPT_SGA) &&
3000 TELOPT_U_MODE(TELOPT_SGA) >= TN_NG_RQ) {
3001 if (tn_sopt(DO, TELOPT_SGA) < 0)
3003 TELOPT_UNANSWERED_DO(TELOPT_SGA) = 1;
3007 if (!TELOPT_U(TELOPT_ECHO) &&
3008 TELOPT_U_MODE(TELOPT_ECHO) >= TN_NG_RQ) {
3009 if (tn_sopt(DO, TELOPT_ECHO) < 0)
3011 TELOPT_UNANSWERED_DO(TELOPT_ECHO) = 1;
3015 if (!TELOPT_ME(TELOPT_ECHO) &&
3016 TELOPT_ME_MODE(TELOPT_ECHO) >= TN_NG_RQ) {
3017 if (tn_sopt(WILL, TELOPT_ECHO) < 0)
3019 TELOPT_UNANSWERED_WILL(TELOPT_ECHO) = 1;
3023 debug(F100,"tn_ini about to send WILL TTYPE if requested","",0);
3025 Talking to TELNET port, so send WILL TERMINAL TYPE and DO SGA.
3026 Also send WILL NAWS if we know our screen dimensions.
3028 if (!TELOPT_ME(TELOPT_TTYPE) &&
3029 TELOPT_ME_MODE(TELOPT_TTYPE) >= TN_NG_RQ) {
3030 if ((x = tn_sopt(WILL,TELOPT_TTYPE)) < 0) {
3031 debug(F101,"tn_ini tn_sopt WILL TTYPE failed","",x);
3034 TELOPT_UNANSWERED_WILL(TELOPT_TTYPE) = 1;
3036 debug(F100,"tn_ini sent WILL TTYPE ok","",0);
3038 if (!TELOPT_U(TELOPT_TTYPE) &&
3039 TELOPT_U_MODE(TELOPT_TTYPE) >= TN_NG_RQ) {
3040 if ((x = tn_sopt(DO,TELOPT_TTYPE)) < 0) {
3041 debug(F101,"tn_ini tn_sopt DO TTYPE failed","",x);
3044 TELOPT_UNANSWERED_DO(TELOPT_TTYPE) = 1;
3046 debug(F100,"tn_ini sent DO TTYPE ok","",0);
3048 if (!TELOPT_ME(TELOPT_BINARY) &&
3049 TELOPT_ME_MODE(TELOPT_BINARY) >= TN_NG_RQ) {
3050 if (tn_sopt(WILL, TELOPT_BINARY) < 0)
3052 TELOPT_UNANSWERED_WILL(TELOPT_BINARY) = 1;
3055 if (!TELOPT_U(TELOPT_BINARY) &&
3056 TELOPT_U_MODE(TELOPT_BINARY) >= TN_NG_RQ) {
3057 if (tn_sopt(DO, TELOPT_BINARY) < 0)
3059 TELOPT_UNANSWERED_DO(TELOPT_BINARY) = 1;
3064 if (!TELOPT_ME(TELOPT_SNDLOC) &&
3065 TELOPT_ME_MODE(TELOPT_SNDLOC) >= TN_NG_RQ) {
3066 if (tn_sopt(WILL, TELOPT_SNDLOC) < 0)
3068 TELOPT_UNANSWERED_WILL(TELOPT_SNDLOC) = 1;
3072 #endif /* CK_SNDLOC */
3073 #ifdef CK_ENVIRONMENT
3075 if (!TELOPT_U(TELOPT_FORWARD_X) &&
3076 TELOPT_U_MODE(TELOPT_FORWARD_X) >= TN_NG_RQ) {
3077 if (tn_sopt(WILL, TELOPT_FORWARD_X) < 0)
3079 TELOPT_UNANSWERED_WILL(TELOPT_FORWARD_X) = 1;
3082 #endif /* FORWARD_X */
3084 if (!TELOPT_ME(TELOPT_XDISPLOC) &&
3085 TELOPT_ME_MODE(TELOPT_XDISPLOC) >= TN_NG_RQ) {
3086 if (tn_sopt(WILL, TELOPT_XDISPLOC) < 0)
3088 TELOPT_UNANSWERED_WILL(TELOPT_XDISPLOC) = 1;
3091 #endif /* CK_XDISPLOC */
3092 /* Will send terminal environment. */
3093 if (!TELOPT_ME(TELOPT_NEWENVIRON) &&
3094 TELOPT_ME_MODE(TELOPT_NEWENVIRON) >= TN_NG_RQ) {
3095 if (tn_sopt(WILL, TELOPT_NEWENVIRON) < 0)
3097 TELOPT_UNANSWERED_WILL(TELOPT_NEWENVIRON) = 1;
3100 if (!TELOPT_U(TELOPT_NEWENVIRON) &&
3101 TELOPT_U_MODE(TELOPT_NEWENVIRON) >= TN_NG_RQ) {
3102 if (tn_sopt(DO, TELOPT_NEWENVIRON) < 0)
3104 TELOPT_UNANSWERED_DO(TELOPT_NEWENVIRON) = 1;
3107 #endif /* CK_ENVIRONMENT */
3109 /* Take care of any other telnet options that require handling. */
3111 for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
3113 case TELOPT_AUTHENTICATION:
3114 case TELOPT_ENCRYPTION:
3118 case TELOPT_NEWENVIRON:
3120 case TELOPT_XDISPLOC:
3124 case TELOPT_START_TLS:
3125 case TELOPT_FORWARD_X:
3129 if (TELOPT_OK(opt)) {
3130 if (!TELOPT_ME(opt) &&
3131 TELOPT_ME_MODE(opt) >= TN_NG_RQ) {
3132 if (tn_sopt(WILL, opt) < 0)
3134 TELOPT_UNANSWERED_WILL(opt) = 1;
3137 if (!TELOPT_U(opt) &&
3138 TELOPT_U_MODE(opt) >= TN_NG_RQ) {
3139 if (tn_sopt(DO, opt) < 0)
3141 TELOPT_UNANSWERED_DO(opt) = 1;
3148 if (tn_wait("pre-encrypt") < 0) {
3155 #ifdef CK_ENCRYPTION
3156 if (tn_init) /* tn_ini() may be called recursively */
3159 if (!TELOPT_ME(TELOPT_ENCRYPTION) &&
3160 TELOPT_ME_MODE(TELOPT_ENCRYPTION) >= TN_NG_RQ) {
3161 if (tn_sopt(WILL, TELOPT_ENCRYPTION) < 0)
3163 TELOPT_UNANSWERED_WILL(TELOPT_ENCRYPTION) = 1;
3166 if (!TELOPT_U(TELOPT_ENCRYPTION) &&
3167 TELOPT_U_MODE(TELOPT_ENCRYPTION) >= TN_NG_RQ) {
3168 if (tn_sopt(DO, TELOPT_ENCRYPTION) < 0)
3170 TELOPT_UNANSWERED_DO(TELOPT_ENCRYPTION) = 1;
3174 /* If we are going to encrypt, we want to do it before we send any more */
3175 /* data, especially the terminal type and environment variables. */
3177 if (tn_wait("post-encrypt") < 0) {
3183 #endif /* CK_ENCRYPTION */
3187 if (tn_init) /* tn_ini() may be called recursively */
3191 /* Kermit Server negotiation must go last */
3192 /* Send U before ME */
3194 if (!TELOPT_U(TELOPT_KERMIT) &&
3195 TELOPT_U_MODE(TELOPT_KERMIT) >= TN_NG_RQ) {
3196 if (tn_sopt(DO, TELOPT_KERMIT) < 0)
3198 TELOPT_UNANSWERED_DO(TELOPT_KERMIT) = 1;
3201 if (!TELOPT_ME(TELOPT_KERMIT) &&
3202 TELOPT_ME_MODE(TELOPT_KERMIT) >= TN_NG_RQ) {
3203 if (tn_sopt(WILL, TELOPT_KERMIT) < 0)
3205 TELOPT_UNANSWERED_WILL(TELOPT_KERMIT) = 1;
3208 #endif /* IKS_OPTION */
3211 if (tn_wait("end of telnet negotiations") < 0) {
3218 tn_sdsb(); /* Send delayed subnegotiations */
3223 /* Start a telnet connection. */
3224 /* Returns -1 on error, 0 if nothing happens, 1 if init msgs sent ok */
3230 debug(F101,"tn_ini ttnproto","",ttnproto);
3231 debug(F101,"tn_ini tn_init","",tn_init);
3233 if (ttnet != NET_TCPB) /* Make sure connection is TCP/IP */
3239 if (tn_init) /* Have we done this already? */
3240 return(0); /* Don't do it again. */
3242 tn_reset(); /* Reset telnet parameters */
3243 tn_begun = 0; /* Reset; will be set by tn_start() */
3245 switch ( ttnproto ) {
3253 debug(F100,"tn_ini telnet negotiations ignored","tn_init",tn_init);
3256 /* Jeff's code from 30 Dec 2005 - doesn't work with SSL POP server */
3260 ttnproto = NP_TELNET; /* pretend it's telnet anyway, */
3261 oldplex = duplex; /* save old duplex value */
3262 duplex = 1; /* and set to half duplex for telnet */
3264 debug(F100,"tn_ini skipping telnet negotiations","",0);
3266 tn_wait("tn_ini - waiting to see if telnet negotiations were sent");
3271 case NP_TCPRAW: /* Raw socket requested. */
3272 debug(F100,"tn_ini telnet negotiations ignored","tn_init",tn_init);
3275 /* My code from 4 Dec 2005 - works with SSL POP server */
3278 case NP_TLS: /* If not talking to a telnet port, */
3279 case NP_SSL_RAW: /* SSL and TLS with Telnet */
3280 case NP_TLS_RAW: /* negotiations disabled. */
3281 ttnproto = NP_TELNET; /* pretend it's telnet anyway, */
3282 oldplex = duplex; /* save old duplex value */
3283 duplex = 1; /* and set to half duplex for telnet */
3285 debug(F100,"tn_ini skipping telnet negotiations","",0);
3287 tn_wait("tn_ini - waiting to see if telnet negotiations were sent");
3290 case NP_TCPRAW: /* Raw socket requested. */
3291 debug(F100,"tn_ini telnet negotiations ignored","tn_init",tn_init);
3293 #endif /* COMMENT */
3294 case NP_KERMIT: /* switching to Telnet protocol */
3297 debug(F101,"tn_ini switching from XXX to Telnet","",ttnproto);
3298 ttnproto = NP_TELNET;
3301 /* We are already using a variation on Telnet protocol */
3306 tn_init = 1; /* Remember successful completion. */
3308 /* Don't send anything else! */
3309 debug(F101,"tn_ini duplex","",duplex);
3310 debug(F101,"tn_ini done, tn_init","",tn_init);
3316 tn_hex(CHAR * buf, int buflen, CHAR * data, int datalen)
3317 #else /* CK_ANSIC */
3318 tn_hex(buf, buflen, data, datalen)
3323 #endif /* CK_ANSIC */
3325 int i = 0, j = 0, k = 0;
3326 CHAR tmp[16]; /* in case value is treated as negative */
3330 for (k=0; k < datalen; k++) {
3331 if (data[k] < 32 || data[k] >= 127) {
3332 sprintf(tmp,"%s%02X ",was_hex?"":"\" ",data[k]);
3335 sprintf(tmp,"%s%c",was_hex?"\"":"",data[k]);
3338 ckstrncat((char *)buf,tmp,buflen);
3341 ckstrncat((char *)buf,"\" ",buflen);
3343 if (datalen <= 0 || data == NULL || buf == NULL || buflen <= 0)
3346 for (i = 0; i < datalen; i++) {
3347 ckstrncat((char *)buf,"\r\n ",buflen);
3348 for (j = 0 ; (j < 16); j++) {
3349 if ((i + j) < datalen)
3350 sprintf((char *)tmp,
3352 (j == 8 ? "| " : ""),
3353 (unsigned int) data[i + j]
3356 sprintf((char *)tmp,
3358 (j == 8 ? "| " : "")
3360 ckstrncat((char *)buf,(char *)tmp,buflen);
3362 ckstrncat((char *)buf," ",buflen);
3363 for (k = 0; (k < 16) && ((i + k) < datalen); k++) {
3364 sprintf((char *)tmp,
3366 (k == 8 ? " " : ""),
3367 isprint((char)(data[i+k])) ? data[i+k] : '.'
3369 ckstrncat((char *)buf,(char *)tmp,buflen);
3373 ckstrncat((char *)buf,"\r\n ",buflen);
3374 #endif /* COMMENT */
3375 return(strlen((char *)buf));
3379 tn_debug(s) char *s; {
3384 void cwrite(unsigned short);
3386 _PROTOTYP (void os2bold, (void));
3387 extern int tt_type_mode;
3390 if (!(tn_deb || debses))
3392 debug(F111,"tn_debug",s,what);
3395 extern unsigned char colorcmd;
3400 if (!scrninitialized[VTERM]) {
3404 SaveCmdMode(x+1,y+1);
3409 if ( ISVTNT(tt_type_mode) && ttnum != -1 && !debses )
3412 RequestVscrnMutex( VTERM, SEM_INDEFINITE_WAIT ) ;
3414 os2bold(); /* Toggle boldness */
3416 cwrite((CHAR) *p++); /* Go boldly ... */
3417 os2bold(); /* Toggle boldness back */
3420 cwrite((CHAR) '\015');
3421 cwrite((CHAR) '\012');
3424 cwrite((CHAR) '\015');
3425 cwrite((CHAR) '\012');
3427 ReleaseVscrnMutex(VTERM) ;
3429 if (what != W_CONNECT && what != W_DIALING &&
3430 what != W_COMMAND && what != W_NOTHING)
3431 return; /* CONNECT/command must be active */
3434 #endif /* NOLOCAL */
3438 Process in-band Telnet negotiation characters from the remote host.
3439 Call with the telnet IAC character and the current duplex setting
3440 (0 = remote echo, 1 = local echo), and a pointer to a function to call
3441 to read more characters. Returns:
3442 6 if DO LOGOUT was received and accepted
3443 5 if the Kermit start of packet character has changed
3444 4 if state of remote Internet Kermit Service has changed
3445 3 if a quoted IAC was received
3446 2 if local echo must be changed to remote
3447 1 if remote echo must be changed to local
3448 0 if nothing happens or no action necessary
3449 -1 on failure (= internal or i/o error)
3453 tn_siks(cmd) int cmd; { /* TELNET SEND IKS SUB */
3456 extern CHAR mystch; /* Outgoing Start of Packet Char */
3462 if (ttnet != NET_TCPB) return(0); /* Must be TCP/IP */
3463 if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
3465 if (cmd < KERMIT_START || cmd > KERMIT_RESP_STOP) /* Illegal subcommand */
3469 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
3473 if (cmd == KERMIT_START || cmd == KERMIT_RESP_START) {
3474 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
3475 } else if (cmd == KERMIT_STOP || cmd == KERMIT_RESP_STOP) {
3476 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
3477 } else if (cmd == KERMIT_REQ_STOP)
3478 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 1;
3479 else if (cmd == KERMIT_REQ_START)
3480 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 1;
3482 if (cmd == KERMIT_SOP) {
3483 buf[0] = (CHAR) IAC;
3485 buf[2] = (CHAR) TELOPT_KERMIT;
3486 buf[3] = (CHAR) (cmd & 0xff);
3487 buf[4] = (CHAR) mystch;
3488 buf[5] = (CHAR) IAC;
3492 if (tn_deb || debses || deblog)
3493 ckmakmsg( tn_msg_out,TN_MSG_LEN,"TELNET SENT SB KERMIT SOP ",
3494 ckctox(mystch,1)," IAC SE",NULL);
3497 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3500 debug(F101,tn_msg_out,"",cmd);
3501 if (tn_deb || debses) tn_debug(tn_msg_out);
3503 rc = ( ttol(buf,7) < 7 ); /* Send it. */
3505 ReleaseTelnetMutex();
3510 buf[0] = (CHAR) IAC;
3512 buf[2] = (CHAR) TELOPT_KERMIT;
3513 buf[3] = (CHAR) (cmd & 0xff);
3514 buf[4] = (CHAR) IAC;
3519 if (tn_deb || debses || deblog) {
3522 case KERMIT_START: s = "START"; break;
3523 case KERMIT_STOP: s = "STOP"; break;
3524 case KERMIT_REQ_START: s = "REQ-START"; break;
3525 case KERMIT_REQ_STOP: s = "REQ-STOP"; break;
3526 case KERMIT_RESP_START: s = "RESP-START"; break;
3527 case KERMIT_RESP_STOP: s = "RESP-STOP"; break;
3529 ckmakmsg( tn_msg_out,TN_MSG_LEN,
3530 "TELNET SENT SB kermit ",s," IAC SE",NULL);
3534 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3537 debug(F101,tn_msg_out,"",cmd);
3538 if (tn_deb || debses) tn_debug(tn_msg_out);
3540 rc = ( ttol(buf,6) < 6 ); /* Send it. */
3542 ReleaseTelnetMutex();
3549 #endif /* IKS_OPTION */
3551 /* tn_sb() performs Telnet Subnegotiation Parsing and Debugging */
3552 /* returns <= 0 on error, 1 on success */
3553 /* the length returned includes the IAC SE bytes */
3556 #ifdef CK_ANSIC /* TELNET SB */
3557 tn_sb( int opt, int * len, int (*fn)(int) )
3559 tn_sb( opt, len, fn ) int opt; int * len; int (*fn)();
3560 #endif /* CK_ANSIC */
3562 int c, x, y, n, m, flag;
3563 /* if (!IS_TELNET()) return(1); */
3565 debug(F100,"Entering tn_sb()","",0);
3566 *len = 0; /* Initialize Len to 0 */
3567 n = flag = 0; /* Flag for when done reading SB */
3568 while (n < TSBUFSIZ) { /* Loop looking for IAC SE */
3569 if ((y = (*fn)(0)) < 0) /* Read a byte */
3571 y &= 0xff; /* Make sure it's just 8 bits. */
3572 sb[n++] = (char) y; /* Deposit in buffer. */
3573 if (seslog && sessft == XYFT_D) { /* Take care of session log */
3576 if (y == IAC) { /* If this is an IAC */
3577 if (flag) { /* If previous char was IAC */
3578 n--; /* it's quoted, keep one IAC */
3579 flag = 0; /* and turn off the flag. */
3580 } else flag = 1; /* Otherwise set the flag. */
3581 } else if (flag) { /* Something else following IAC */
3582 if (y == SE) /* If not SE, it's a protocol error */
3584 else if (y == DONT) { /* Used DONT instead of SE */
3586 "TELNET Subnegotiation error - used DONT instead of SE!",
3590 if (tn_deb || debses)
3592 "TELNET Subnegotiation error - used DONT instead of SE!");
3595 } else { /* Other protocol error */
3602 if ( opt == TELOPT_FORWARD_X && sb[0] == FWDX_DATA &&
3603 n >= (TSBUFSIZ-4) && !flag ) {
3604 /* do not let the buffer over flow */
3605 /* write the data to the channel and continue processing */
3606 /* the incoming data until IAC SE is reached. */
3611 if ( deblog || tn_deb || debses ) {
3613 ckmakmsg( tn_msg,TN_MSG_LEN,
3614 "TELNET RCVD SB ",TELOPT(opt),
3615 " DATA(buffer-full) ",NULL);
3616 tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&sb[1],n-3);
3618 ckstrncat(tn_msg," SE",TN_MSG_LEN);
3620 ckstrncat(tn_msg," IAC DONT",TN_MSG_LEN);
3622 ckstrncat(tn_msg," IAC SE",TN_MSG_LEN);
3623 debug(F100,tn_msg,"",0);
3624 if (tn_deb || debses)
3629 if ( fwdx_tn_sb(sb,n) < 0 ) {
3630 debug(F100,"fxdx_tn_sb() failed","",0);
3631 /* We can't return though because that would leave */
3632 /* data to be forwarded in the queue to the be sent */
3633 /* to the terminal emulator. */
3635 /* reset leave the msg type and channel number in place */
3638 #endif /* CK_FORWARD_X */
3640 debug(F111,"tn_sb end of while loop","flag",flag);
3641 if (!flag) { /* Make sure we got a valid SB */
3642 debug(F111, "TELNET Subnegotiation prematurely broken","opt",opt);
3643 if (tn_deb || debses) {
3644 ckmakmsg( tn_msg, TN_MSG_LEN,
3645 "TELNET ", TELOPT(opt),
3646 " Subnegotiation prematurely broken",NULL
3651 /* Was -1 but that would be an I/O error, so absorb it and go on. */
3655 if (deblog || tn_deb || debses) {
3658 for (i = 0; i < 16; i++)
3660 if (opt == TELOPT_NAWS) {
3668 if (opt == TELOPT_FORWARD_X)
3670 else if (opt == TELOPT_KERMIT)
3672 else if (opt == TELOPT_LFLOW)
3674 else if (opt == TELOPT_COMPORT)
3678 if (opt == TELOPT_ENCRYPTION) {
3680 if (sb[1] < ENCTYPE_CNT) {
3681 s[1] = enctype_names[sb[1]];
3688 s[2] = "FB64_IV_OK";
3691 s[2] = "FB64_IV_BAD";
3694 s[2] = "FB64_CHALLENGE";
3697 s[2] = "FB64_RESPONSE";
3704 if (opt == TELOPT_AUTHENTICATION) {
3706 s[1] = AUTHTYPE_NAME(sb[1]);
3707 s[2] = AUTHMODE_NAME(sb[2]);
3726 s[3] = "NTLM_CHALLENGE";
3735 s[3] = "NTLM_RESPONSE";
3744 s[3] = "NTLM_ACCEPT";
3746 case 1: /* KERBEROS_v4 */
3750 case 2: /* KERBEROS_v5 */
3761 s[3] = "NTLM_REJECT";
3763 case 1: /* KERBEROS_V4 */
3767 case 2: /* KERBEROS_V5 */
3777 case 2: /* KERBEROS_V5 */
3778 s[3] = "FORWARD_ACCEPT";
3785 s[3] = "FORWARD_ACCEPT";
3787 case 2: /* KERBEROS_V5 */
3788 s[3] = "FORWARD_REJECT";
3795 s[3] = "FORWARD_REJECT";
3797 case 2: /* KERBEROS_V5 */
3798 s[3] = "TLS_VERIFY";
3822 case TELOPT_FORWARD_X:
3831 case TELOPT_COMPORT:
3832 s[0] = "SET-BAUDRATE";
3834 case TELOPT_AUTHENTICATION:
3837 for (; i < n-2; i += 2) {
3838 if ( AUTHTYPE_NAME_OK(sb[i]) &&
3839 AUTHMODE_NAME_OK(sb[i]))
3840 ckmakmsg( tn_msg, TN_MSG_LEN,
3841 AUTHTYPE_NAME(sb[i])," ",
3842 AUTHMODE_NAME(sb[i+1])," "
3845 ckmakxmsg(tn_msg, TN_MSG_LEN,
3846 AUTHTYPE_NAME(sb[i]),
3850 AUTHMODE_NAME(sb[i+1]),
3856 ckstrncat(hexbuf,tn_msg,sizeof(hexbuf));
3861 case TELOPT_ENCRYPTION:
3864 s[i] = enctype_names[sb[i]];
3869 case TELOPT_START_TLS:
3879 case TELOPT_FORWARD_X:
3883 s[0] = "RESTART-ANY";
3888 case TELOPT_COMPORT:
3889 s[0] = "SET-DATASIZE";
3891 case TELOPT_NEWENVIRON:
3894 case TELOPT_AUTHENTICATION:
3897 s[1] = AUTHTYPE_NAME(sb[1]);
3898 s[2] = AUTHMODE_NAME(sb[2]);
3912 s[3] = "NTLM_CHALLENGE";
3921 s[3] = "NTLM_RESPONSE";
3930 s[3] = "NTLM_ACCEPT";
3932 case AUTHTYPE_KERBEROS_V4:
3936 case AUTHTYPE_KERBEROS_V5:
3944 s[3] = "NTLM_REJECT";
3946 case AUTHTYPE_KERBEROS_V4:
3950 case AUTHTYPE_KERBEROS_V5:
3960 case AUTHTYPE_KERBEROS_V5:
3961 s[3] = "FORWARD_ACCEPT";
3968 s[3] = "FORWARD_ACCEPT";
3970 case AUTHTYPE_KERBEROS_V5:
3971 s[3] = "FORWARD_REJECT";
3978 s[3] = "FORWARD_REJECT";
3980 case AUTHTYPE_KERBEROS_V5:
3981 s[3] = "TLS_VERIFY";
4001 case TELOPT_ENCRYPTION:
4003 s[1] = enctype_names[sb[1]];
4012 s[2] = "FB64_IV_OK";
4016 s[2] = "FB64_IV_BAD";
4020 s[2] = "FB64_CHALLENGE";
4024 s[2] = "FB64_RESPONSE";
4032 case TELOPT_FORWARD_X:
4036 s[0] = "RESTART-XON";
4041 case TELOPT_COMPORT:
4042 s[0] = "SET-PARITY";
4044 case TELOPT_AUTHENTICATION:
4047 case TELOPT_ENCRYPTION:
4054 case TELOPT_FORWARD_X:
4060 case TELOPT_COMPORT:
4061 s[0] = "SET-STOPSIZE";
4063 case TELOPT_ENCRYPTION:
4070 case TELOPT_FORWARD_X:
4071 s[0] = "OPTION_DATA";
4073 case TELOPT_ENCRYPTION:
4074 s[0] = "REQUEST-START";
4076 case TELOPT_COMPORT:
4077 s[0] = "SET-CONTROL";
4083 case TELOPT_FORWARD_X:
4086 case TELOPT_ENCRYPTION:
4087 s[0] = "REQUEST-END";
4089 case TELOPT_COMPORT:
4090 s[0] = "NOTIFY-LINESTATE";
4096 case TELOPT_FORWARD_X:
4099 case TELOPT_ENCRYPTION:
4102 case TELOPT_COMPORT:
4103 s[0] = "NOTIFY-MODEMSTATE";
4110 s[0] = "RESP-START";
4112 case TELOPT_ENCRYPTION:
4115 case TELOPT_COMPORT:
4116 s[0] = "FLOWCONTROL-SUSPEND";
4125 case TELOPT_COMPORT:
4126 s[0] = "FLOWCONTROL-RESUME";
4132 case TELOPT_COMPORT:
4133 s[0] = "SET-LINESTATE-MASK";
4139 case TELOPT_COMPORT:
4140 s[0] = "SET-MODEMSTATE-MASK";
4146 case TELOPT_COMPORT:
4147 s[0] = "PURGE-DATA";
4155 case TELOPT_COMPORT:
4156 s[0] = "S_SIGNATURE";
4162 case TELOPT_COMPORT:
4163 s[0] = "S_SET-BAUDRATE";
4169 case TELOPT_COMPORT:
4170 s[0] = "S_SET-DATASIZE";
4176 case TELOPT_COMPORT:
4177 s[0] = "S_SET-PARITY";
4183 case TELOPT_COMPORT:
4184 s[0] = "S_SET-STOPSIZE";
4190 case TELOPT_COMPORT:
4191 s[0] = "S_SET-CONTROL";
4197 case TELOPT_COMPORT:
4198 s[0] = "S_NOTIFY-LINESTATE";
4204 case TELOPT_COMPORT:
4205 s[0] = "S_NOTIFY-MODEMSTATE";
4211 case TELOPT_COMPORT:
4212 s[0] = "S_FLOWCONTROL-SUSPEND";
4218 case TELOPT_COMPORT:
4219 s[0] = "S_FLOWCONTROL-RESUME";
4225 case TELOPT_COMPORT:
4226 s[0] = "S_SET-LINESTATE-MASK";
4232 case TELOPT_COMPORT:
4233 s[0] = "S_SET-MODEMSTATE-MASK";
4239 case TELOPT_COMPORT:
4240 s[0] = "S_PURGE-DATA";
4248 int len, param, param_len;
4249 ckmakmsg( tn_msg, TN_MSG_LEN,
4251 TELOPT(opt)," ",NULL);
4252 len = strlen(tn_msg);
4253 for (param = 0; param <= 15; param++) {
4254 param_len = strlen(s[param]);
4255 if (param_len > 0) {
4256 strcpy(&tn_msg[len], s[param]);
4258 tn_msg[len++] = ' ';
4264 ckmakxmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD SB ",TELOPT(opt)," ",
4265 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
4268 for (i = 0; i < 16; i++) {
4270 ckstrncat(tn_msg,s[i],TN_MSG_LEN);
4271 ckstrncat(tn_msg," ",TN_MSG_LEN);
4275 #endif /* M_XENIX */
4276 tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&sb[i],n-2-i);
4278 ckstrncat(tn_msg," SE",TN_MSG_LEN);
4280 ckstrncat(tn_msg," IAC DONT",TN_MSG_LEN);
4282 ckstrncat(tn_msg," IAC SE",TN_MSG_LEN);
4283 debug(F100,tn_msg,"",0);
4284 if (tn_deb || debses)
4287 debug(F111,"tn_sb","len",n);
4289 *len = n; /* return length */
4290 return(1); /* success */
4293 static char rows_buf[16] = { 0, 0 }; /* LINES Environment variable */
4294 static char cols_buf[16] = { 0, 0 }; /* COLUMNS Enviornment variable */
4295 static char term_buf[64] = { 0, 0 }; /* TERM Environment variable */
4300 _PROTOTYP(int tgetent,(char *, char *));
4301 #endif /* COHERENT */
4304 _PROTOTYP(int tgetent,(char *, char *));
4307 extern char * trmbuf; /* Real curses */
4308 #endif /* CK_CURSES */
4310 #ifdef CK_ENCRYPTION
4314 /* Prevent Encryption from being negotiated */
4315 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
4316 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
4318 /* Cancel any negotiation that might have started */
4321 if (TELOPT_ME(TELOPT_ENCRYPTION) ||
4322 TELOPT_UNANSWERED_WILL(TELOPT_ENCRYPTION)) {
4323 TELOPT_ME(TELOPT_ENCRYPTION) = 0;
4324 if (tn_sopt(WONT,TELOPT_ENCRYPTION) < 0)
4326 TELOPT_UNANSWERED_WONT(TELOPT_ENCRYPTION) = 1;
4328 if (TELOPT_U(TELOPT_ENCRYPTION) ||
4329 TELOPT_UNANSWERED_DO(TELOPT_ENCRYPTION)) {
4330 TELOPT_U(TELOPT_ENCRYPTION) = 0;
4331 if (tn_sopt(DONT,TELOPT_ENCRYPTION) < 0)
4333 TELOPT_UNANSWERED_DONT(TELOPT_ENCRYPTION) = 1;
4337 #endif /* CK_ENCRYPTION */
4339 /* The following note came from the old SGA negotiation code. This should */
4340 /* no longer be necessary with the New Telnet negotiation state machine. */
4342 Note: The following is proper behavior, and required for talking to the
4343 Apertus interface to the NOTIS library system, e.g. at Iowa State U:
4344 scholar.iastate.edu. Without this reply, the server hangs forever. This
4345 code should not be loop-inducing, since C-Kermit never sends WILL SGA as
4346 an initial bid, so if DO SGA comes, it is never an ACK.
4350 -1 = Telnet Option negotiation error
4351 -2 = Connection closed by peer
4352 -3 = Connection closed by us
4363 #ifdef CK_ANSIC /* TELNET DO OPTION */
4364 tn_xdoop(CHAR z, int echo, int (*fn)(int))
4366 tn_xdoop(z, echo, fn) CHAR z; int echo; int (*fn)();
4367 #endif /* CK_ANSIC */
4374 int inautodl = 0, cmdadl = 1;
4377 extern int autodl, inautodl, cmdadl;
4378 #endif /* CK_AUTODL */
4380 #endif /* IKS_OPTION */
4382 /* if (!IS_TELNET()) return(7); */
4384 /* Have IAC, read command character. */
4386 while ((c = (*fn)(0)) == -1); /* Read command character */
4389 c &= 0xFF; /* Strip high bits */
4391 if (!TELCMD_OK(c)) {
4393 if (tn_deb || debses || deblog) {
4394 ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD UNKNOWN (",
4395 ckitoa(c),")",NULL);
4396 debug(F101,tn_msg,"",c);
4397 if (tn_deb || debses)
4403 if (ttnproto == NP_NONE) {
4404 debug(F100,"tn_doop discovered a Telnet command",
4405 "ttnproto = NP_TELNET",0);
4406 ttnproto = NP_TELNET;
4408 if (seslog && sessft == XYFT_D) { /* Copy to session log, if any. */
4413 if (c == (CHAR) IAC) /* Quoted IAC */
4416 if (c < SB) { /* Other command with no arguments. */
4418 if (deblog || tn_deb || debses) {
4419 ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD ",TELCMD(c),NULL,NULL);
4420 debug(F101,tn_msg,"",c);
4421 if (tn_deb || debses) tn_debug(tn_msg);
4424 switch (c) { /* What we would like to do here */
4425 case TN_GA: /* Is substitute ASCII characters */
4426 break; /* for the Telnet Command so that */
4427 case TN_EL: /* the command may be processed by */
4428 break; /* either the internal emulator or */
4429 case TN_EC: /* by the superior process or shell */
4433 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
4435 ttol((CHAR *)"[Yes]\015\012",7);
4437 ReleaseTelnetMutex();
4443 #endif /* BETADEBUG */
4469 /* SB, WILL, WONT, DO, or DONT need more bytes... */
4471 if ((x = (*fn)(0)) < 0) /* Get the option. */
4473 x &= 0xff; /* Trim to 8 bits. */
4475 if (seslog && sessft == XYFT_D) { /* Session log */
4479 if ((deblog || tn_deb || debses) && c != SB) {
4480 ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD ",TELCMD(c)," ",TELOPT(x));
4481 debug(F101,tn_msg,"",x);
4482 if (tn_deb || debses) tn_debug(tn_msg);
4485 /* Now handle the command */
4489 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
4493 if (x == TELOPT_FORWARD_X) {
4494 if (!fwdx_server_avail() || !(fwdx_no_encrypt ||
4496 (ssl_active_flag || tls_active_flag)
4501 #ifdef CK_ENCRYPTION
4502 (ck_tn_encrypting() && ck_tn_decrypting())
4503 #else /* CK_ENCRYPTION */
4505 #endif /* CK_ENCRYPTION */
4507 TELOPT_U_MODE(TELOPT_FORWARD_X) = TN_NG_RF;
4508 TELOPT_ME_MODE(TELOPT_FORWARD_X) = TN_NG_RF;
4511 #endif /* CK_FORWARD_X */
4512 if (!TELOPT_OK(x) || TELOPT_U_MODE(x) == TN_NG_RF) {
4513 if (tn_sopt(DONT,x) < 0)
4515 if (TELOPT_UNANSWERED_DO(x))
4516 TELOPT_UNANSWERED_DO(x) = 0;
4517 } else if (!TELOPT_U(x)) {
4518 if (!TELOPT_UNANSWERED_DO(x)) {
4519 if (tn_sopt(DO,x) < 0)
4522 if (TELOPT_UNANSWERED_DO(x))
4523 TELOPT_UNANSWERED_DO(x) = 0;
4528 case TELOPT_START_TLS:
4530 If my proposal is accepted, at this point the Telnet
4531 protocol is turned off and a TLS negotiation takes
4534 Start by sending SB START_TLS FOLLOWS to signal
4535 we are ready. Wait for the peer to send the same
4536 and then start the TLS negotiation.
4538 If the TLS negotiation succeeds we call tn_ini()
4539 again to reset the telnet state machine and restart
4540 the negotiation process over the now secure link.
4542 If the TLS negotiation fails, we call ttclos()
4543 to terminate the connection.
4545 Only the server should receive a WILL START_TLS
4547 tn_ssbopt(TELOPT_START_TLS,1,NULL,0);
4548 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 1;
4552 #ifdef CK_AUTHENTICATION
4553 case TELOPT_AUTHENTICATION: {
4554 /* We now have to perform a SB SEND to identify the */
4555 /* supported authentication types to the other side. */
4556 extern int authentication_version;
4559 /* if we have an outstanding DO START_TLS then we must
4560 * wait for the response before we determine what to do
4562 if (TELOPT_UNANSWERED_DO(TELOPT_START_TLS)) {
4563 TELOPT_SB(TELOPT_START_TLS).start_tls.auth_request = 1;
4567 authentication_version = AUTHTYPE_AUTO;
4568 ck_tn_auth_request();
4571 #endif /* CK_AUTHENTICATION */
4572 #ifdef CK_ENCRYPTION
4573 case TELOPT_ENCRYPTION:
4574 if (!(TELOPT_ME(TELOPT_AUTHENTICATION) ||
4575 TELOPT_U(TELOPT_AUTHENTICATION))
4577 if (tn_sopt(DONT,x) < 0)
4581 if (ck_tn_auth_in_progress()) {
4582 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 1;
4584 /* Perform subnegotiation */
4585 ck_encrypt_send_support();
4587 if (!(TELOPT_ME(x) || TELOPT_UNANSWERED_WILL(x))
4588 && TELOPT_ME_MODE(x) != TN_NG_RF) {
4589 if (tn_sopt(WILL, x) < 0)
4591 TELOPT_UNANSWERED_WILL(x) = 1;
4595 #endif /* CK_ENCRYPTION */
4598 if (!TELOPT_ME(x)) {
4599 /* Tell the other side what Start of Packet Character */
4600 tn_siks(KERMIT_SOP); /* SOP */
4602 if (!TELOPT_UNANSWERED_WILL(x) &&
4603 TELOPT_ME_MODE(x) != TN_NG_RF) {
4604 if (tn_sopt(WILL, x) < 0)
4606 TELOPT_UNANSWERED_WILL(x) = 1;
4610 #endif /* IKS_OPTION */
4612 if (!TELOPT_ME(x)) {
4613 if (!TELOPT_UNANSWERED_WILL(x) &&
4614 TELOPT_ME_MODE(x) >= TN_NG_RQ) {
4615 if (tn_sopt(WILL, x) < 0)
4617 TELOPT_UNANSWERED_WILL(x) = 1;
4623 if (TELOPT_UNANSWERED_DO(x))
4624 TELOPT_UNANSWERED_DO(x) = 0;
4630 tn_ssbopt(TELOPT_TTYPE,TELQUAL_SEND,NULL,0);
4631 TELOPT_UNANSWERED_SB(TELOPT_TTYPE)=1;
4633 #ifdef CK_ENVIRONMENT
4634 case TELOPT_NEWENVIRON: /* SB NEW-ENVIRON SEND */
4636 char request[6]; /* request it */
4637 sprintf(request,"%cUSER",TEL_ENV_VAR); /* safe */
4638 tn_ssbopt(TELOPT_NEWENVIRON,TELQUAL_SEND,request,
4640 TELOPT_UNANSWERED_SB(TELOPT_NEWENVIRON)=1;
4643 #endif /* CK_ENVIRONMENT */
4646 if (TELOPT_UNANSWERED_DO(x))
4647 TELOPT_UNANSWERED_DO(x) = 0;
4652 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
4655 if (TELOPT_U(x) || TELOPT_UNANSWERED_DO(x)) {
4656 /* David Borman says we should not respond DONT when
4657 * the WONT is a response to a DO that we sent.
4658 * Nor should we send one if the state is already WONT
4659 * such as when we do not recognize the option since
4660 * options are initialized in the WONT/DONT state.
4662 if (!(TELOPT_UNANSWERED_DO(x) || TELOPT_UNANSWERED_DONT(x)))
4663 if (tn_sopt(DONT,x) < 0)
4665 if (TELOPT_UNANSWERED_DONT(x))
4666 TELOPT_UNANSWERED_DONT(x) = 0;
4667 if (TELOPT_UNANSWERED_DO(x))
4668 TELOPT_UNANSWERED_DO(x) = 0;
4674 case TELOPT_START_TLS:
4676 if (TELOPT_U_MODE(x) == TN_NG_MU) {
4677 printf("Telnet Start-TLS refused.\n");
4679 whyclosed = WC_TELOPT;
4682 if (TELOPT_SB(x).start_tls.auth_request) {
4683 extern int authentication_version;
4684 TELOPT_SB(x).start_tls.auth_request = 0;
4685 authentication_version = AUTHTYPE_AUTO;
4686 ck_tn_auth_request();
4691 #ifdef CK_AUTHENTICATION
4692 case TELOPT_AUTHENTICATION:
4693 if (sstelnet && TELOPT_U_MODE(x) == TN_NG_MU) {
4694 printf("Telnet authentication refused.\n");
4696 whyclosed = WC_TELOPT;
4698 } else if (TELOPT_U_MODE(x) == TN_NG_RQ) {
4699 TELOPT_U_MODE(x) = TN_NG_AC;
4701 if (ck_tn_auth_in_progress())
4702 printf("Telnet authentication refused.\n");
4703 #ifdef CK_ENCRYPTION
4705 if (tn_no_encrypt()<0)
4708 #endif /* CK_ENCRYPTION */
4710 #endif /* CK_AUTHENTICATION */
4711 #ifdef CK_ENCRYPTION
4712 case TELOPT_ENCRYPTION:
4715 #endif /* CK_ENCRYPTION */
4718 TELOPT_SB(x).kermit.u_start = 0;
4719 TELOPT_SB(x).kermit.me_req_start = 0;
4720 TELOPT_SB(x).kermit.me_req_stop = 0;
4722 #endif /* IKS_OPTION */
4724 /* The client does not support NAWS. */
4725 /* Assume a height of 24 and a width of 80 */
4737 VscrnSetWidth(VTERM, w);
4738 VscrnSetHeight(VTERM, h+(tt_status[VTERM]?1:0));
4747 VscrnSetWidth(VCMD, w);
4748 VscrnSetHeight(VCMD, h);
4756 #endif /* NOLOCAL */
4757 /* Add LINES and COLUMNS to the environment */
4758 ckmakmsg((char *)rows_buf,16,"LINES=",ckitoa(h),
4760 ckmakmsg((char *)cols_buf,16,"COLUMNS=",ckitoa(w),
4766 #endif /* NOPUTENV */
4767 #endif /* OS2ORUNIX */
4773 if (TELOPT_UNANSWERED_DO(x))
4774 TELOPT_UNANSWERED_DO(x) = 0;
4780 if (TELOPT_UNANSWERED_DONT(x))
4781 TELOPT_UNANSWERED_DONT(x) = 0;
4782 if (TELOPT_UNANSWERED_DO(x))
4783 TELOPT_UNANSWERED_DO(x) = 0;
4785 if (TELOPT_U_MODE(x) == TN_NG_MU) {
4786 ckmakmsg( tn_msg,TN_MSG_LEN,
4787 "Peer refuses TELNET DO ",TELOPT(x),
4788 " negotiations - terminating connection",NULL
4790 debug(F100,tn_msg,"",0);
4791 if (tn_deb || debses) tn_debug(tn_msg);
4792 printf("%s\n",tn_msg);
4794 whyclosed = WC_TELOPT;
4798 if (x == TELOPT_ECHO && !echo) /* Special handling for echo */
4799 return(1); /* because we allow 'duplex' */
4800 #endif /* COMMENT */
4805 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
4808 if (!TELOPT_OK(x) || TELOPT_ME_MODE(x) == TN_NG_RF) {
4809 if (tn_sopt(WONT,x) < 0)
4811 if (TELOPT_UNANSWERED_WILL(x))
4812 TELOPT_UNANSWERED_WILL(x) = 0;
4813 } else if (!TELOPT_ME(x)) {
4814 if (!TELOPT_UNANSWERED_WILL(x)) {
4815 if (tn_sopt(WILL,x) < 0)
4818 if (TELOPT_UNANSWERED_WILL(x))
4819 TELOPT_UNANSWERED_WILL(x) = 0;
4824 case TELOPT_START_TLS:
4826 If my proposal is accepted at this point the Telnet
4827 protocol is turned off and a TLS negotiation takes
4830 Start by sending SB START_TLS FOLLOWS to signal
4831 we are ready. Wait for the peer to send the same
4832 and then start the TLS negotiation.
4834 If the TLS negotiation succeeds we call tn_ini()
4835 again to reset the telnet state machine and restart
4836 the negotiation process over the now secure link.
4838 If the TLS negotiation fails, we call ttclos()
4839 to terminate the connection. Then we set the
4840 U_MODE and ME_MODE for TELOPT_START_TLS to REFUSE
4841 and then call ttopen() to create a new connection
4842 to the same host but this time do not attempt
4845 Only the client should receive DO START_TLS.
4847 tn_ssbopt(TELOPT_START_TLS,1,NULL,0);
4848 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 1;
4852 #ifdef CK_AUTHENTICATION
4853 case TELOPT_AUTHENTICATION: {
4854 /* We don't know what authentication we are using yet */
4855 /* but it is not NULL until a failure is detected so */
4856 /* use AUTO in the meantime. */
4857 extern int authentication_version;
4858 authentication_version = AUTHTYPE_AUTO;
4861 #endif /* CK_AUTHENTICATION */
4862 #ifdef CK_ENCRYPTION
4863 case TELOPT_ENCRYPTION:
4864 if (!(TELOPT_ME(TELOPT_AUTHENTICATION) ||
4865 TELOPT_U(TELOPT_AUTHENTICATION))
4867 if (tn_sopt(WONT,x) < 0)
4871 if (!(TELOPT_U(x) || TELOPT_UNANSWERED_DO(x))
4872 && TELOPT_U_MODE(x) != TN_NG_RF) {
4873 if (tn_sopt(DO, x) < 0)
4875 TELOPT_UNANSWERED_DO(x) = 1;
4879 #endif /* CK_ENCRYPTION */
4882 /* If currently processing Kermit server packets, must tell the other side */
4884 debug(F111,"tn_doop","what",what);
4885 debug(F111,"tn_doop","server",server);
4887 debug(F111,"tn_doop","autodl",autodl);
4888 debug(F111,"tn_doop","inautodl",inautodl);
4889 debug(F111,"tn_doop","cmdadl",cmdadl);
4890 #endif /* CK_AUTODL */
4894 || (local && ((what == W_CONNECT && autodl) ||
4895 (what != W_CONNECT && inautodl)))
4896 || (!local && cmdadl)
4897 #endif /* CK_AUTODL */
4899 tn_siks(KERMIT_START); /* START */
4902 /* Tell the other side what Start of Packet Character */
4903 tn_siks(KERMIT_SOP); /* SOP */
4904 if (!TELOPT_UNANSWERED_DO(x) &&
4905 TELOPT_U_MODE(x) != TN_NG_RF) {
4906 if (tn_sopt(DO, x) < 0)
4908 TELOPT_UNANSWERED_DO(x) = 1;
4912 #endif /* IKS_OPTION */
4916 if (!TELOPT_UNANSWERED_DO(x) &&
4917 TELOPT_U_MODE(x) >= TN_NG_RQ) {
4918 if (tn_sopt(DO, x) < 0)
4920 TELOPT_UNANSWERED_DO(x) = 1;
4926 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
4930 TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 1;
4932 #endif /* CK_NAWS */
4935 ttclos(0); /* And then hangup */
4936 whyclosed = WC_TELOPT;
4940 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
4941 if (tn_sndloc() < 0)
4944 TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 1;
4947 #endif /* CK_SNDLOC */
4949 case TELOPT_FORWARD_X:
4950 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
4951 if (fwdx_send_options() < 0) {
4952 if (tn_sopt(DONT,x) < 0)
4954 TELOPT_UNANSWERED_DONT(x) = 1;
4957 TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 1;
4960 #endif /* CK_FORWARD_X */
4962 case TELOPT_COMPORT: {
4963 extern int reliable;
4964 if (!tn_delay_sb || !tn_outst(0) || tn_init) {
4965 if (tn_sndcomport() < 0)
4968 TELOPT_SB(TELOPT_COMPORT).comport.need_to_send = 1;
4970 /* Telnet -> Serial -> ??? is not a reliable connection. */
4974 #endif /* TN_COMPORT */
4977 if (TELOPT_UNANSWERED_WILL(x))
4978 TELOPT_UNANSWERED_WILL(x) = 0;
4984 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
4987 if (TELOPT_ME(x) || TELOPT_UNANSWERED_WILL(x)) {
4988 /* David Borman says we should not respond WONT when
4989 * the DONT is a response to a WILL that we sent.
4990 * Nor should we send one if the state is already WONT
4991 * such as when we do not recognize the option since
4992 * options are initialized in the WONT/DONT state.
4994 if (!(TELOPT_UNANSWERED_WILL(x) || TELOPT_UNANSWERED_WONT(x)))
4995 if (tn_sopt(WONT,x) < 0)
4998 if (TELOPT_UNANSWERED_WILL(x))
4999 TELOPT_UNANSWERED_WILL(x) = 0;
5000 if (TELOPT_UNANSWERED_WONT(x))
5001 TELOPT_UNANSWERED_WONT(x) = 0;
5007 case TELOPT_START_TLS:
5008 if (!sstelnet && TELOPT_ME_MODE(x) == TN_NG_MU) {
5009 printf("Telnet Start-TLS refused.\n");
5011 whyclosed = WC_TELOPT;
5016 #ifdef CK_AUTHENTICATION
5017 case TELOPT_AUTHENTICATION:
5018 if (!sstelnet && TELOPT_ME_MODE(x) == TN_NG_MU) {
5020 if (tls_active_flag) {
5021 TELOPT_ME_MODE(x) = TN_NG_AC;
5026 printf("Telnet authentication refused.\n");
5028 whyclosed = WC_TELOPT;
5031 } else if (TELOPT_ME_MODE(x) == TN_NG_RQ) {
5032 TELOPT_ME_MODE(x) = TN_NG_AC;
5034 if (ck_tn_auth_in_progress())
5035 printf("Telnet authentication refused.\n");
5036 #ifdef CK_ENCRYPTION
5038 if (tn_no_encrypt()<0)
5041 #endif /* CK_ENCRYPTION */
5043 #endif /* CK_AUTHENTICATION */
5044 case TELOPT_ENCRYPTION:
5045 #ifdef CK_ENCRYPTION
5047 #endif /* CK_ENCRYPTION */
5051 TELOPT_SB(x).kermit.me_start = 0;
5052 #endif /* IKS_OPTION */
5058 if (TELOPT_UNANSWERED_WILL(x))
5059 TELOPT_UNANSWERED_WILL(x) = 0;
5060 if (TELOPT_UNANSWERED_WONT(x))
5061 TELOPT_UNANSWERED_WONT(x) = 0;
5063 if (TELOPT_ME_MODE(x) == TN_NG_MU) {
5064 ckmakmsg( tn_msg,TN_MSG_LEN,
5065 "Peer refuses TELNET WILL ",TELOPT(x),
5066 " negotiations - terminating connection",
5069 debug(F100,tn_msg,"",0);
5070 if (tn_deb || debses) tn_debug(tn_msg);
5071 printf("%s\n",tn_msg);
5073 whyclosed = WC_TELOPT;
5078 if ((y = tn_sb(x,&n,fn)) <= 0)
5082 /* Do not process subnegotiations other than START_TLS after we */
5083 /* have agreed to begin the TLS negotiation sequence. */
5084 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows &&
5085 x != TELOPT_START_TLS)
5089 if (!TELOPT_OK(x)) {
5090 ckhexdump("unknown telnet subnegotiation",sb,n);
5092 } else if ( !(TELOPT_ME(x) || TELOPT_U(x)) ) {
5093 ckhexdump("telnet option not negotiated",sb,n);
5096 if (TELOPT_UNANSWERED_WILL(x)) {
5097 TELOPT_UNANSWERED_WILL(x) = 0;
5099 ckmakmsg(tn_msg,TN_MSG_LEN,
5100 "TELNET DO ",TELOPT(x),
5101 "(implied by receipt of SB - protocol error ignored)",
5104 debug(F100,tn_msg,"",0);
5105 if (tn_deb || debses) tn_debug(tn_msg);
5107 if (TELOPT_UNANSWERED_DO(x)) {
5108 TELOPT_UNANSWERED_DO(x) = 0;
5110 ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET WILL ",TELOPT(x),
5111 " (implied by receipt of SB - protocol error ignored)",
5113 debug(F100,tn_msg,"",0);
5114 if (tn_deb || debses) tn_debug(tn_msg);
5118 TELOPT_UNANSWERED_SB(x)=0;
5121 case TELOPT_FORWARD_X:
5122 return(fwdx_tn_sb(sb, n));
5123 #endif /* CK_FORWARD_X */
5125 case TELOPT_START_TLS: {
5127 the other side is saying SB START_TLS FOLLOWS
5128 the incoming channel is now ready for starting the
5131 int def_tls_u_mode, def_tls_me_mode;
5132 int def_enc_u_mode, def_enc_me_mode;
5139 TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 1;
5140 /* Preserve the default modes and make sure we will */
5141 /* refuse START_TLS when we retry. */
5143 def_tls_u_mode = TELOPT_DEF_S_U_MODE(TELOPT_START_TLS);
5144 def_tls_me_mode = TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS);
5145 TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
5146 TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS)= TN_NG_RF;
5147 #ifdef CK_ENCRYPTION
5148 def_enc_u_mode = TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION);
5149 def_enc_me_mode = TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION);
5150 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
5151 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION)= TN_NG_RF;
5152 #endif /* CK_ENCRYPTION */
5154 def_tls_u_mode = TELOPT_DEF_C_U_MODE(TELOPT_START_TLS);
5155 def_tls_me_mode = TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS);
5156 TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
5157 TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS)= TN_NG_RF;
5158 #ifdef CK_ENCRYPTION
5159 def_enc_u_mode = TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION);
5160 def_enc_me_mode = TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION);
5161 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
5162 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION)= TN_NG_RF;
5163 #endif /* CK_ENCRYPTION */
5169 if (ck_tn_tls_negotiate()<0) {
5170 /* we failed. disconnect and if we are the client */
5171 /* then reconnect and try without START_TLS. */
5177 printf("TLS failed: Disconnecting.\n");
5178 TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = def_tls_u_mode;
5179 TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = def_tls_me_mode;
5180 #ifdef CK_ENCRYPTION
5181 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = def_enc_u_mode;
5182 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
5183 #endif /* CK_ENCRYPTION */
5185 whyclosed = WC_TELOPT;
5186 ttnproto = NP_TELNET;
5190 extern int tls_norestore;
5191 #endif /* NOLOCAL */
5192 printf("TLS failed: Disconnecting...\n");
5193 #ifdef CK_ENCRYPTION
5194 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = def_enc_u_mode;
5195 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
5196 #endif /* CK_ENCRYPTION */
5197 /* if START_TLS is not REQUIRED, then retry without it */
5198 if ( def_tls_me_mode != TN_NG_MU ) {
5199 extern char ttname[];
5202 #endif /* NOLOCAL */
5204 whyclosed = WC_TELOPT;
5207 #endif /* NOLOCAL */
5208 ttnproto = NP_TELNET;
5209 printf("Reconnecting without TLS.\n");
5211 if (ttopen(ttname,&x,mdmtyp,0)<0)
5214 TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) =
5216 TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) =
5219 whyclosed = WC_TELOPT;
5220 ttnproto = NP_TELNET;
5225 #ifdef CK_AUTHENTICATION
5226 /* we succeeded. restart telnet negotiations from */
5227 /* the beginning. However, if we have received a */
5228 /* client certificate and we are a server, then do */
5229 /* not offer TELOPT_AUTH. */
5230 if ( ck_tn_auth_valid() == AUTH_VALID ) {
5231 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_AC;
5232 TELOPT_DEF_S_ME_MODE(TELOPT_AUTHENTICATION)= TN_NG_AC;
5234 #endif /* CK_AUTHENTICATION */
5235 ttnproto = NP_TELNET;
5240 /* Restore the default modes */
5242 TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = def_tls_u_mode;
5243 TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = def_tls_me_mode;
5244 #ifdef CK_ENCRYPTION
5245 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = def_enc_u_mode;
5246 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
5247 #endif /* CK_ENCRYPTION */
5249 TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = def_tls_u_mode;
5250 TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = def_tls_me_mode;
5251 #ifdef CK_ENCRYPTION
5252 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = def_enc_u_mode;
5253 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
5254 #endif /* CK_ENCRYPTION */
5259 #ifdef CK_AUTHENTICATION
5260 case TELOPT_AUTHENTICATION:
5261 if (ck_tn_sb_auth((char *)sb,n) < 0) {
5262 if (sstelnet && TELOPT_U_MODE(x) == TN_NG_MU) {
5264 whyclosed = WC_TELOPT;
5266 } else if (!sstelnet && TELOPT_ME_MODE(x) == TN_NG_MU) {
5268 whyclosed = WC_TELOPT;
5271 if (TELOPT_ME_MODE(x) == TN_NG_RQ)
5272 TELOPT_ME_MODE(x) = TN_NG_AC;
5273 if (TELOPT_U_MODE(x) == TN_NG_RQ)
5274 TELOPT_U_MODE(x) = TN_NG_AC;
5278 if (tn_sopt(WONT,x) < 0)
5283 if (tn_sopt(DONT,x) < 0)
5286 #ifdef CK_ENCRYPTION
5287 if (tn_no_encrypt()<0)
5289 #endif /* CK_ENCRYPTION */
5291 #ifdef CK_ENCRYPTION
5292 if (!ck_tn_auth_in_progress()) { /* we are finished */
5293 if (ck_tn_authenticated() == AUTHTYPE_SSL) {
5294 /* TLS was successful. Disable ENCRYPTION */
5295 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
5296 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
5298 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send) {
5299 ck_encrypt_send_support();
5300 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 0;
5303 #endif /* CK_ENCRYPTION */
5306 #endif /* CK_AUTHENTICATION */
5307 #ifdef CK_ENCRYPTION
5308 case TELOPT_ENCRYPTION:
5309 if (ck_tn_sb_encrypt((char *)sb, n) < 0) {
5310 if (TELOPT_U_MODE(x) == TN_NG_MU ||
5311 TELOPT_ME_MODE(x) == TN_NG_MU)
5314 whyclosed = WC_TELOPT;
5317 if (TELOPT_ME_MODE(x) == TN_NG_RQ)
5318 TELOPT_ME_MODE(x) = TN_NG_AC;
5319 if (TELOPT_U_MODE(x) == TN_NG_RQ)
5320 TELOPT_U_MODE(x) = TN_NG_AC;
5324 if (tn_sopt(WONT,x) < 0)
5329 if (tn_sopt(DONT,x) < 0)
5334 #endif /* CK_ENCRYPTION */
5337 return(iks_tn_sb(sb, n-2));
5338 #endif /* IKS_OPTION */
5340 case TELOPT_COMPORT:
5341 return(tnc_tn_sb(sb, n-2));
5342 #endif /* TN_COMPORT */
5345 case TELQUAL_SEND: /* SEND terminal type? */
5346 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
5347 if (tn_sttyp() < 0) /* Yes, so send it. */
5350 TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 1;
5353 case TELQUAL_IS: { /* IS terminal type? */
5354 /* IS terminal type -- remote gave us its current type */
5357 CHAR oldterm[64], *p;
5359 /* Isolate the specified terminal type string */
5360 while (sb[i++] != IAC) {
5361 if (i == 40 || /* max len of term string - RFC */
5369 strupr(&(sb[1])); /* Upper case it */
5370 for (i = 0; i <= max_tt; i++) { /* find it in our list */
5371 if (!strcmp(&(sb[1]),tt_info[i].x_name)
5372 && i != TT_VTNT) /* can't support VTNT as server */
5374 /* Set terminal type to the one chosen */
5381 strcmp(&(sb[1]),TELOPT_SB(TELOPT_TTYPE).term.type)) {
5382 /* Couldn't find the specified term type */
5384 strcpy(TELOPT_SB(TELOPT_TTYPE).term.type,&(sb[1]));
5386 tn_ssbopt(TELOPT_TTYPE,TELQUAL_SEND,NULL,0);
5387 TELOPT_UNANSWERED_SB(TELOPT_TTYPE)=1;
5391 p = (CHAR *) getenv("TERM");
5393 ckstrncpy((char *)oldterm,(char *)p,63);
5396 cklower((char *)&(sb[1])); /* Lower case new term */
5397 ckmakmsg(term_buf,64,"TERM=",(char *)&(sb[1]),NULL,NULL);
5401 #endif /* NOPUTENV */
5402 #endif /* OS2ORUNIX */
5407 if (tgetent(trmbuf,(char *)&sb[1]) < 1) {
5408 /* Unsupported terminal. If new and old terminal */
5409 /* types do not match, ask for another type. */
5410 if (strcmp((char *)oldterm,(char *)&sb[1])) {
5412 tn_ssbopt(TELOPT_TTYPE,TELQUAL_SEND,NULL,0);
5413 TELOPT_UNANSWERED_SB(TELOPT_TTYPE)=1;
5417 #endif /* COHERENT */
5418 #endif /* MYCURSES */
5419 #endif /* CK_CURSES */
5424 #ifdef CK_ENVIRONMENT
5426 case TELOPT_XDISPLOC: /* Send X-Display Location */
5427 if (sb[0] == TELQUAL_SEND) {/* SEND X-Display Loc? */
5428 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
5429 if (tn_sxdisploc() < 0) /* Yes, so send it. */
5432 TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 1;
5435 /* IS -- X Display Location (not supported) */
5436 else if (sb[0] == TELQUAL_IS) {
5438 /* Isolate the specified X-display string */
5439 while (sb[i++] != IAC) {
5447 debug(F110,"TELNET SB XDISPLOC IS",&sb[1],0);
5450 #endif /* CK_XDISPLOC */
5451 #endif /* CK_ENVIRONMENT */
5460 /* At this point sb[] should contain width and height */
5461 if (sb[i] == IAC) i++;
5462 w = (sb[i++] << 8); /* save upper height */
5463 if (sb[i] == IAC) i++;
5464 w += sb[i++]; /* save the width */
5465 if (sb[i] == IAC) i++;
5466 h = (sb[i++] << 8); /* save upper height */
5467 if (sb[i] == IAC) i++;
5469 debug(F111,"tn_doop NAWS SB","width",w);
5470 debug(F111,"tn_doop NAWS SB","height",h);
5477 if (tcp_incoming || inserver) {
5481 VscrnSetWidth(VTERM, w);
5482 VscrnSetHeight(VTERM, h+(tt_status[VTERM]?1:0));
5485 cmd_cols = tt_cols[VCMD] = w;
5486 cmd_rows = tt_rows[VCMD] = h;
5487 VscrnSetWidth(VCMD, w);
5488 VscrnSetHeight(VCMD, h);
5499 VscrnSetWidth(VCMD, w);
5500 VscrnSetHeight(VCMD, h);
5508 #endif /* NOLOCAL */
5510 /* Add LINES and COLUMNS to the environment */
5511 ckmakmsg((char *)rows_buf,16,"LINES=",ckitoa(h),NULL,NULL);
5512 ckmakmsg((char *)cols_buf,16,"COLUMNS=",ckitoa(w),NULL,NULL);
5517 #endif /* NOPUTENV */
5518 #endif /* OS2ORUNIX */
5521 #ifdef CK_ENVIRONMENT
5522 case TELOPT_NEWENVIRON:
5524 case TELQUAL_IS: /* IS */
5525 case TELQUAL_INFO: /* INFO */
5526 if (sb[0] == TELQUAL_IS)
5527 debug(F101,"tn_doop NEW-ENV SB IS","",n-3);
5529 debug(F101,"tn_doop NEW-ENV SB INFO","",n-3);
5530 if (sstelnet || inserver) { /* Yes, receive it. */
5531 if (tn_rnenv((CHAR *)&sb[1],n-3) < 0)
5535 case TELQUAL_SEND: /* SEND */
5536 if ( sstelnet || inserver ) /* ignore if server */
5538 /* We need to take the sb[] and build a structure */
5539 /* containing all of the variables and types that */
5540 /* we are supposed to keep track of and send to */
5541 /* the host, then call tn_snenv(). */
5542 /* Or we can punt ... */
5543 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
5544 if (tn_snenv((CHAR *)&sb[1],n-3) < 0) /* Yes, send it. */
5549 xxx = (CHAR *) malloc(n-1);
5551 unsigned char * xxx;
5552 xxx = (unsigned char *) malloc(n-1);
5554 /* Postpone sending until end of tn_ini() */
5555 TELOPT_SB(TELOPT_NEWENVIRON).env.str = xxx;
5556 if (TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
5557 memcpy((char *)TELOPT_SB(TELOPT_NEWENVIRON).env.str,
5558 (char *)&sb[1],n-3);
5559 TELOPT_SB(TELOPT_NEWENVIRON).env.str[n-3] = IAC;
5560 TELOPT_SB(TELOPT_NEWENVIRON).env.str[n-2] = '\0';
5561 TELOPT_SB(TELOPT_NEWENVIRON).env.len = n-3;
5562 TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 1;
5568 #endif /* CK_ENVIRONMENT */
5570 case TELOPT_SNDLOC: {
5573 debug(F110,"TELNET Send-Location",sb,0);
5577 #endif /* CK_SNDLOC */
5585 #ifdef CK_ANSIC /* TELNET DO OPTION */
5586 tn_doop(CHAR z, int echo, int (*fn)(int))
5588 tn_doop(z, echo, fn) CHAR z; int echo; int (*fn)();
5589 #endif /* CK_ANSIC */
5593 debug(F101,"tn_doop char","",z);
5594 debug(F101,"tn_doop ttnproto","",ttnproto);
5596 if (!IS_TELNET()) return(3);
5599 debug(F101,"tn_doop ssl_raw_flag","",ssl_raw_flag);
5600 if (ssl_raw_flag || tls_raw_flag) return(7);
5602 debug(F100,"tn_doop ttnproto proceeding...","",0);
5604 if (z != (CHAR) IAC) {
5605 debug(F101,"tn_doop bad call","",z);
5608 if (ttnet != NET_TCPB) /* Check network type */
5610 if (ttnproto != NP_TELNET &&
5611 ttnproto != NP_NONE) /* Check protocol */
5614 x = tn_xdoop(z,echo,fn);
5615 if (x >= 0 && !tn_begun) {
5618 return(y < 0 ? y : x);
5621 #ifdef CK_ENVIRONMENT
5623 /* Telnet receive new environment */
5624 /* Returns -1 on error, 0 if nothing happens, 1 on success */
5625 /* In order for this code to work, sb[len] == IAC */
5626 /* We currently only support the USER environment variable */
5630 tn_rnenv(CHAR * sb, int len)
5632 tn_rnenv(sb, len) CHAR * sb; int len;
5633 #endif /* CK_ANSIC */
5634 /* tn_rnenv */ { /* Receive new environment */
5637 char * reply = 0, * s = 0;
5638 int i,j,k,n; /* Worker. */
5639 int type = 0; /* 0 for NONE, 1 for VAR, 2 for USERVAR, */
5640 /* 3 for VALUE in progress */
5642 if (ttnet != NET_TCPB) return(0);
5643 if (ttnproto != NP_TELNET) return(0);
5644 if (sb == NULL) return(-1);
5646 if (len == 0) return(1);
5649 Pairs of <type> [VAR=0, VALUE=1, ESC=2, USERVAR=3] <value> "unterminated"
5650 follow here until done...
5652 for (i = 0, j = 0, k = 0, type = 0, varname[0]= '\0'; i <= len; i++) {
5654 case TEL_ENV_VAR: /* VAR */
5655 case TEL_ENV_USERVAR: /* USERVAR */
5656 case IAC: /* End of the list */
5658 case 0: /* Nothing in progress */
5659 /* If we get IAC only, then that means there were */
5660 /* no environment variables to send. we are done */
5661 if (j == 0 && sb[i] == IAC)
5663 case 1: /* VAR in progress */
5664 case 2: /* USERVAR in progress */
5665 case 3: /* VALUE in progress */
5668 debug(F111,"tn_rnenv varname",varname,type);
5669 debug(F111,"tn_rnenv value",value,type);
5670 if (!strcmp(varname,"USER")) {
5671 #ifdef CK_AUTHENTICATION
5672 if (ck_tn_auth_valid() != AUTH_VALID) {
5673 extern char szUserNameRequested[];
5674 debug(F100,"tn_rnenv != AUTH_VALID","",0);
5675 ckstrncpy(szUserNameRequested,value,UIDBUFLEN);
5676 ckstrncpy(uidbuf,value,UIDBUFLEN);
5678 if (ssl_active_flag) {
5679 if ( tls_is_user_valid(ssl_con, uidbuf) ) {
5680 extern char szUserNameAuthenticated[];
5681 ckstrncpy(szUserNameAuthenticated,uidbuf,
5683 auth_finished(AUTH_VALID);
5685 } else if (tls_active_flag) {
5686 if ( tls_is_user_valid(tls_con, uidbuf) ) {
5687 extern char szUserNameAuthenticated[];
5688 ckstrncpy(szUserNameAuthenticated,uidbuf,
5690 auth_finished(AUTH_VALID);
5694 } else { /* AUTH_VALID */
5696 debug(F110,"tn_rnenv AUTH_VALID uidbuf",uidbuf,0);
5699 x = ckstrcmp(value,uidbuf,-1,0); /* case insensitive */
5701 /* NTLM authentication returns names of the form */
5702 /* DOMAIN\user. We need to check to see of the */
5703 /* USER VAR contains a domain name or not. If */
5704 /* not, then we do not want to change state if */
5705 /* the uidbuf matches the USER VAR when the */
5706 /* DOMAIN is ignored. */
5707 if ( x && ck_tn_authenticated() == AUTHTYPE_NTLM ) {
5708 char * s1=NULL, * s2=NULL;
5711 len1 = strlen(value);
5712 for ( i=len1-1 ; i>=0 ; i--) {
5713 if ( value[i] == '\\' ) {
5714 s1 = &value[i+1]; /* DOMAIN found */
5720 len2 = strlen(uidbuf);
5721 for ( i=len2-1 ; i>=0 ; i--) {
5722 if ( uidbuf[i] == '\\' ) {
5723 s2 = &uidbuf[i+1]; /* DOMAIN found */
5729 x = ckstrcmp(value,s2,-1,0);
5734 x = ckstrcmp(value,uidbuf,-1,1); /* case sensitive */
5737 extern char szUserNameRequested[];
5738 ckstrncpy(uidbuf,value,UIDBUFLEN);
5739 ckstrncpy(szUserNameRequested,value,UIDBUFLEN);
5740 auth_finished(AUTH_USER);
5742 if (ssl_active_flag || tls_active_flag) {
5743 if ( tls_is_user_valid(ssl_con, uidbuf) )
5744 auth_finished(AUTH_VALID);
5749 #else /* CK_AUTHENTICATION */
5750 ckstrncpy(uidbuf,value,UIDBUFLEN);
5751 #endif /* CK_AUTHENTICATION */
5759 type = (sb[i] == TEL_ENV_USERVAR ? 2 : /* USERVAR */
5760 sb[i] == TEL_ENV_VAR ? 1 : /* VAR */
5764 case TEL_ENV_VALUE: /* VALUE */
5765 if ( type == 1 || type == 2 )
5768 case TEL_ENV_ESC: /* ESC */
5769 /* Take next character literally */
5772 /* otherwise, fallthrough so byte will be added to string. */
5775 case 1: /* VAR in progress */
5776 case 2: /* USERVAR in progress */
5778 varname[j++] = sb[i];
5790 /* These are for Microsoft SFU version 2 Telnet Server */
5791 #define SFUTLNTVER "SFUTLNTVER"
5792 #define SFUTLNTMODE "SFUTLNTMODE"
5793 #define SFUTLNTVER_VALUE "2"
5794 #define SFUTLNTMODE_VALUE "console" /* The other value is "stream" */
5796 /* Telnet send new environment */
5797 /* Returns -1 on error, 0 if nothing happens, 1 on success */
5798 /* In order for this code to work, sb[len] == IAC */
5802 tn_snenv(CHAR * sb, int len)
5804 tn_snenv(sb, len) CHAR * sb; int len;
5805 #endif /* CK_ANSIC */
5806 /* tn_snenv */ { /* Send new environment */
5808 char * reply = 0, * s = 0;
5809 int i,j,n; /* Worker. */
5810 int type = 0; /* 0 for NONE, 1 for VAR, 2 for USERVAR in progress */
5811 extern int ck_lcname;
5812 char localuidbuf[UIDBUFLEN]; /* (Initialized just below) */
5816 localuidbuf[0] = '\0';
5817 if (ttnet != NET_TCPB) return(0);
5818 if (ttnproto != NP_TELNET) return(0);
5819 if (!sb) return(-1);
5822 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
5828 if (TELOPT_U(TELOPT_FORWARD_X)) {
5831 #endif /* CK_FORWARD_X */
5832 disp = (char *)tn_get_display();
5835 ckstrncpy(localuidbuf,uidbuf,UIDBUFLEN);
5836 cklower(localuidbuf);
5840 ckhexdump((CHAR *)"tn_snenv sb[]",sb,len);
5841 debug(F110,"tn_snenv uidbuf",uidbuf,0);
5842 debug(F110,"tn_snenv localuidbuf",localuidbuf,0);
5843 debug(F110,"tn_snenv tn_env_sys",tn_env_sys,0);
5844 debug(F110,"tn_snenv tn_env_disp",tn_env_disp,0);
5845 debug(F110,"tn_snenv disp",disp,0);
5847 /* First determine the size of the buffer we will need */
5848 for (i = 0, j = 0, n = 0, type = 0, varname[0]= '\0'; i <= len; i++) {
5850 case TEL_ENV_VAR: /* VAR */
5851 case TEL_ENV_USERVAR: /* USERVAR */
5852 case IAC: /* End of the list */
5854 case 0: /* Nothing in progress */
5855 /* If we get IAC only, then that means send all */
5856 /* VAR and USERVAR. */
5857 if (!(j == 0 && sb[i] == IAC))
5859 case 1: /* VAR in progress */
5861 if (!varname[0]) { /* Send All */
5863 n += strlen(uu) + 4 + 2;
5865 n += strlen(tn_env_job) + 3 + 2;
5867 n += strlen(tn_env_acct) + 4 + 2;
5869 n += strlen(tn_env_prnt) + 7 + 2;
5871 n += strlen(tn_env_sys) + 10 + 2;
5873 n += strlen(disp) + 7 + 2;
5874 } else if (!strcmp(varname,"USER") && uu[0])
5875 n += strlen(uu) + 4 + 2;
5876 else if (!strcmp(varname,"JOB") && tn_env_job[0])
5877 n += strlen(tn_env_job) + 3 + 2;
5878 else if (!strcmp(varname,"ACCT") && tn_env_acct[0])
5879 n += strlen(tn_env_acct) + 4 + 2;
5880 else if (!strcmp(varname,"PRINTER") && tn_env_prnt[0])
5881 n += strlen(tn_env_prnt) + 7 + 2;
5882 else if (!strcmp(varname,"SYSTEMTYPE") && tn_env_sys[0])
5883 n += strlen(tn_env_sys) + 10 + 2;
5884 else if (!strcmp(varname,"DISPLAY") && disp)
5885 n += strlen(disp) + 7 + 2;
5886 /* If we get IAC only, then that means send all */
5887 /* VAR and USERVAR. */
5888 if (!(j == 0 && sb[i] == IAC))
5890 case 2: /* USERVAR in progress */
5892 if (!varname[0]) { /* Send All */
5894 for ( x=0 ; x<8 ; x++ ) {
5895 if ( tn_env_uservar[x][0] &&
5896 tn_env_uservar[x][1] )
5897 n += strlen(tn_env_uservar[x][0])
5898 + strlen(tn_env_uservar[x][1]) + 2;
5901 /* For compatibility with Microsoft Telnet Server */
5902 n += strlen(SFUTLNTVER) + strlen(SFUTLNTVER_VALUE) + 2;
5903 n += strlen(SFUTLNTMODE) +
5904 strlen(SFUTLNTMODE_VALUE) + 2;
5907 if ( tn_loc && tn_loc[0] )
5908 n += strlen("LOCATION") + strlen(tn_loc) + 2;
5909 #endif /* CK_SNDLOC */
5911 else if (tn_sfu && !strcmp(varname,SFUTLNTVER))
5912 n += strlen(SFUTLNTVER) + strlen(SFUTLNTVER_VALUE) + 2;
5913 else if (tn_sfu && !strcmp(varname,SFUTLNTMODE))
5914 n += strlen(SFUTLNTMODE) + strlen(SFUTLNTMODE_VALUE) + 2;
5916 else if ( tn_loc && tn_loc[0] && !strcmp(varname,"LOCATION"))
5917 n += strlen("LOCATION") + strlen(tn_loc) + 2;
5918 #endif /* CK_SNDLOC */
5921 for ( x=0 ; x<8 ; x++ ) {
5922 if ( tn_env_uservar[x][0] &&
5923 tn_env_uservar[x][1] &&
5924 !strcmp(varname,tn_env_uservar[x][0]))
5925 n += strlen(tn_env_uservar[x][0])
5926 + strlen(tn_env_uservar[x][1]) + 2;
5933 type = (sb[i] == TEL_ENV_USERVAR ? 2 : /* USERVAR */
5934 sb[i] == TEL_ENV_VAR ? 1 : /* VAR */
5938 case TEL_ENV_VALUE: /* VALUE */
5939 /* Protocol Error */
5940 debug(F100, "TELNET Subnegotiation error - VALUE in SEND", "",0);
5941 if (tn_deb || debses)
5942 tn_debug("TELNET Subnegotiation error - VALUE in SEND");
5944 case TEL_ENV_ESC: /* ESC */
5949 varname[j++] = sb[i];
5952 reply = malloc(n + 16); /* Leave room for IAC stuff */
5954 debug(F100, "TELNET Subnegotiation error - malloc failed", "",0);
5955 if (tn_deb || debses)
5956 tn_debug("TELNET Subnegotiation error - malloc failed");
5958 /* Send a return packet with no variables so that the host */
5959 /* may continue with additional negotiations */
5960 if (tn_ssbopt(TELOPT_NEWENVIRON,TELQUAL_IS,"",0) < 0)
5965 /* Now construct the real reply */
5967 n = 0; /* Start at beginning of buffer */
5969 Pairs of <type> [VAR=0, VALUE=1, ESC=2, USERVAR=3] <value> "unterminated"
5970 follow here until done...
5972 for (i = 0, j = 0, type = 0, varname[0]= '\0'; i <= len; i++) {
5974 case TEL_ENV_VAR: /* VAR */
5975 case TEL_ENV_USERVAR: /* USERVAR */
5976 case IAC: /* End of the list */
5978 case 0: /* Nothing in progress */
5979 /* If we get IAC only, then that means send all */
5980 /* VAR and USERVAR. */
5981 if (!(j == 0 && sb[i] == IAC))
5983 case 1: /* VAR in progress */
5988 reply[n] = TEL_ENV_VAR; /* VAR */
5989 strcpy(&reply[n+1],"USER");
5990 reply[n+5] = TEL_ENV_VALUE; /* VALUE */
5991 strcpy(&reply[n+6],uu);
5992 n += strlen(uu) + 4 + 2;
5994 if (tn_env_job[0]) {
5995 reply[n] = TEL_ENV_VAR; /* VAR */
5996 strcpy(&reply[n+1],"JOB");
5997 reply[n+4] = TEL_ENV_VALUE; /* VALUE */
5998 strcpy(&reply[n+5],tn_env_job);
5999 n += strlen(tn_env_job) + 3 + 2;
6001 if (tn_env_acct[0]) {
6002 reply[n] = TEL_ENV_VAR; /* VAR */
6003 strcpy(&reply[n+1],"ACCT");
6004 reply[n+5] = TEL_ENV_VALUE; /* VALUE */
6005 strcpy(&reply[n+6],tn_env_acct);
6006 n += strlen(tn_env_acct) + 4 + 2;
6008 if (tn_env_prnt[0]) {
6009 reply[n] = TEL_ENV_VAR; /* VAR */
6010 strcpy(&reply[n+1],"PRINTER");
6011 reply[n+8] = TEL_ENV_VALUE; /* VALUE */
6012 strcpy(&reply[n+9],tn_env_prnt);
6013 n += strlen(tn_env_prnt) + 7 + 2;
6015 if (tn_env_sys[0]) {
6016 reply[n] = TEL_ENV_VAR; /* VAR */
6017 strcpy(&reply[n+1],"SYSTEMTYPE");
6018 reply[n+11] = TEL_ENV_VALUE; /* VALUE */
6019 strcpy(&reply[n+12],tn_env_sys);
6020 n += strlen(tn_env_sys) + 10 + 2;
6023 reply[n] = TEL_ENV_VAR; /* VAR */
6024 strcpy(&reply[n+1],"DISPLAY");
6025 reply[n+8] = TEL_ENV_VALUE; /* VALUE */
6026 strcpy(&reply[n+9],disp);
6027 n += strlen(disp) + 7 + 2;
6029 } else if (!strcmp(varname,"USER") && uu[0]) {
6030 reply[n] = TEL_ENV_VAR; /* VAR */
6031 strcpy(&reply[n+1],"USER");
6032 reply[n+5] = TEL_ENV_VALUE; /* VALUE */
6033 strcpy(&reply[n+6],uu);
6034 n += strlen(uu) + 4 + 2;
6035 } else if (!strcmp(varname,"JOB") && tn_env_job[0]) {
6036 reply[n] = TEL_ENV_VAR; /* VAR */
6037 strcpy(&reply[n+1],"JOB");
6038 reply[n+4] = TEL_ENV_VALUE; /* VALUE */
6039 strcpy(&reply[n+5],tn_env_job);
6040 n += strlen(tn_env_job) + 3 + 2;
6041 } else if (!strcmp(varname,"ACCT") && tn_env_acct[0]) {
6042 reply[n] = TEL_ENV_VAR; /* VAR */
6043 strcpy(&reply[n+1],"ACCT");
6044 reply[n+5] = TEL_ENV_VALUE; /* VALUE */
6045 strcpy(&reply[n+6],tn_env_acct);
6046 n += strlen(tn_env_acct) + 4 + 2;
6047 } else if (!strcmp(varname,"PRINTER") && tn_env_prnt[0]) {
6048 reply[n] = TEL_ENV_VAR; /* VAR */
6049 strcpy(&reply[n+1],"PRINTER");
6050 reply[n+8] = TEL_ENV_VALUE; /* VALUE */
6051 strcpy(&reply[n+9],tn_env_prnt);
6052 n += strlen(tn_env_prnt) + 7 + 2;
6053 } else if (!strcmp(varname,"SYSTEMTYPE") && tn_env_sys[0]) {
6054 reply[n] = TEL_ENV_VAR; /* VAR */
6055 strcpy(&reply[n+1],"SYSTEMTYPE");
6056 reply[n+11] = TEL_ENV_VALUE; /* VALUE */
6057 strcpy(&reply[n+12],tn_env_sys);
6058 n += strlen(tn_env_sys) + 10 + 2;
6059 } else if (!strcmp(varname,"DISPLAY") && disp) {
6060 reply[n] = TEL_ENV_VAR; /* VAR */
6061 strcpy(&reply[n+1],"DISPLAY");
6062 reply[n+8] = TEL_ENV_VALUE; /* VALUE */
6063 strcpy(&reply[n+9],disp);
6064 n += strlen(disp) + 7 + 2;
6066 /* If we get IAC only, then that means send all */
6067 /* VAR and USERVAR. */
6068 if (!(j == 0 && sb[i] == IAC))
6070 case 2: /* USERVAR in progress */
6075 for ( x=0 ; x<8 ; x++ ) {
6076 if ( tn_env_uservar[x][0] &&
6077 tn_env_uservar[x][1] ) {
6078 reply[n] = TEL_ENV_USERVAR; /* VAR */
6079 y = strlen(tn_env_uservar[x][0]);
6080 strcpy(&reply[n+1],tn_env_uservar[x][0]);
6081 reply[n+y+1] = TEL_ENV_VALUE; /* VALUE */
6082 strcpy(&reply[n+y+2],tn_env_uservar[x][1]);
6083 n += y+strlen(tn_env_uservar[x][1])+2;
6087 /* Compatibility with Microsoft Telnet Server */
6088 reply[n] = TEL_ENV_USERVAR; /* VAR */
6089 strcpy(&reply[n+1],SFUTLNTVER);
6090 reply[n+11] = TEL_ENV_VALUE; /* VALUE */
6091 strcpy(&reply[n+12],SFUTLNTVER_VALUE);
6092 n += strlen(SFUTLNTVER)+strlen(SFUTLNTVER_VALUE)+2;
6094 reply[n] = TEL_ENV_USERVAR; /* VAR */
6095 strcpy(&reply[n+1],SFUTLNTMODE);
6096 reply[n+12] = TEL_ENV_VALUE; /* VALUE */
6097 strcpy(&reply[n+13],SFUTLNTMODE_VALUE);
6098 n += strlen(SFUTLNTMODE)+strlen(SFUTLNTMODE_VALUE)+2;
6100 if (tn_loc && tn_loc[0]) {
6101 reply[n] = TEL_ENV_USERVAR; /* VAR */
6102 strcpy(&reply[n+1],"LOCATION");
6103 reply[n+9] = TEL_ENV_VALUE; /* VALUE */
6104 strcpy(&reply[n+10],tn_loc);
6105 n += strlen("LOCATION") + strlen(tn_loc) + 2;
6107 } else if (tn_sfu && !strcmp(varname,SFUTLNTVER)) {
6108 reply[n] = TEL_ENV_USERVAR; /* VAR */
6109 strcpy(&reply[n+1],SFUTLNTVER);
6110 reply[n+11] = TEL_ENV_VALUE; /* VALUE */
6111 strcpy(&reply[n+12],SFUTLNTVER_VALUE);
6112 n += strlen(SFUTLNTVER) + strlen(SFUTLNTVER_VALUE) + 2;
6113 } else if (tn_sfu && !strcmp(varname,SFUTLNTMODE)) {
6114 reply[n] = TEL_ENV_USERVAR; /* VAR */
6115 strcpy(&reply[n+1],SFUTLNTMODE);
6116 reply[n+12] = TEL_ENV_VALUE; /* VALUE */
6117 strcpy(&reply[n+13],SFUTLNTMODE_VALUE);
6118 n += strlen(SFUTLNTMODE) + strlen(SFUTLNTMODE_VALUE) + 2;
6121 else if (tn_loc && tn_loc[0] && !strcmp(varname,"LOCATION")){
6122 reply[n] = TEL_ENV_USERVAR; /* VAR */
6123 strcpy(&reply[n+1],"LOCATION");
6124 reply[n+9] = TEL_ENV_VALUE; /* VALUE */
6125 strcpy(&reply[n+10],tn_loc);
6126 n += strlen("LOCATION") + strlen(tn_loc) + 2;
6128 #endif /* CK_SNDLOC */
6131 for ( x=0 ; x<8 ; x++ ) {
6132 if ( tn_env_uservar[x][0] &&
6133 tn_env_uservar[x][1] &&
6134 !strcmp(varname,tn_env_uservar[x][0])) {
6135 reply[n] = TEL_ENV_USERVAR; /* VAR */
6136 y = strlen(tn_env_uservar[x][0]);
6137 strcpy(&reply[n+1],tn_env_uservar[x][0]);
6138 reply[n+y+1] = TEL_ENV_VALUE; /* VALUE */
6139 strcpy(&reply[n+y+2],tn_env_uservar[x][1]);
6140 n += y+strlen(tn_env_uservar[x][1])+2;
6148 type = (sb[i] == TEL_ENV_USERVAR ? 2 : /* USERVAR */
6149 sb[i] == TEL_ENV_VAR ? 1 : /* VAR */
6153 case TEL_ENV_VALUE: /* VALUE */
6154 /* Protocol Error */
6155 debug(F100, "TELNET Subnegotiation error - VALUE in SEND", "",0);
6156 if (tn_deb || debses)
6157 tn_debug("TELNET Subnegotiation error - VALUE in SEND");
6158 return(0); /* Was -1 but that would be taken as */
6159 /* an I/O error, so absorb it and go on. */
6160 case TEL_ENV_ESC: /* ESC */
6161 /* Not sure what this for. Quote next character? */
6164 varname[j++] = sb[i];
6167 if (tn_ssbopt(TELOPT_NEWENVIRON,TELQUAL_IS,reply,n) < 0) {
6174 #endif /* CK_ENVIRONMENT */
6176 /* Telnet send terminal type */
6177 /* Returns -1 on error, 0 if nothing happens, 1 if type sent successfully */
6180 tn_sttyp() { /* Send telnet terminal type. */
6181 char *ttn; /* Name of terminal type. */
6183 static int alias = -1; /* which alias are we using ? */
6186 int i, rc; /* Worker. */
6189 if (ttnet != NET_TCPB) return(0);
6190 if (ttnproto != NP_TELNET) return(0);
6192 if (!TELOPT_ME(TELOPT_TTYPE)) return(0);
6195 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6208 } else if (ttnumend) {
6212 if (tt_info[tt_type].x_aliases[++alias] == NULL) {
6215 if (ttnum == tt_type)
6221 if (tt_type >= 0 && tt_type <= max_tt) {
6223 ttn = tt_info[tt_type].x_name;
6225 ttn = tt_info[tt_type].x_aliases[alias];
6233 if (tn_term) { /* Terminal type override? */
6234 debug(F110,"tn_sttyp",tn_term,0);
6239 } else debug(F100,"tn_sttyp no term override","",0);
6242 if (!ttn) { /* If no override, */
6243 ttn = getenv("TERM"); /* get it from the environment. */
6245 #endif /* datageneral */
6246 if ((ttn == ((char *)0)) || ((int)strlen(ttn) >= TSBUFSIZ))
6248 sb_out[0] = (CHAR) IAC; /* I Am a Command */
6249 sb_out[1] = (CHAR) SB; /* Subnegotiation */
6250 sb_out[2] = TELOPT_TTYPE; /* Terminal Type */
6251 sb_out[3] = (CHAR) 0; /* Is... */
6252 for (i = 4; *ttn; ttn++,i++) { /* Copy and uppercase it */
6254 if (!tntermflg && *ttn == '-' &&
6255 (!strcmp(ttn,"-80") || !strcmp(ttn,"-132")))
6259 sb_out[i] = (char) ((!tntermflg && islower(*ttn)) ?
6263 ttn = (char *)sb_out; /* Point back to beginning */
6265 if (deblog || tn_deb || debses) {
6266 sb_out[i] = '\0'; /* For debugging */
6267 ckmakxmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
6268 TELOPT(TELOPT_TTYPE)," IS ",(char *)sb_out+4," IAC SE",
6269 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
6272 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
6273 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
6275 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
6278 debug(F100,tn_msg_out,"",0);
6279 if (tn_deb || debses) tn_debug(tn_msg_out);
6281 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
6283 ReleaseTelnetMutex();
6290 settermtype(tt_type,0);
6293 VscrnIsDirty(VTERM);
6300 #ifdef CK_ENVIRONMENT
6303 /* Telnet send xdisplay location */
6304 /* Returns -1 on error, 0 if nothing happens, 1 if type sent successfully */
6307 tn_sxdisploc() { /* Send telnet X display location. */
6311 if (ttnet != NET_TCPB) return(0);
6312 if (ttnproto != NP_TELNET) return(0);
6314 if (!TELOPT_ME(TELOPT_XDISPLOC)) return(0);
6317 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6323 if (TELOPT_U(TELOPT_FORWARD_X)) {
6326 #endif /* CK_FORWARD_X */
6327 disp = (char *)tn_get_display();
6328 debug(F110,"tn_sxdisploc",disp,0);
6331 /* Can't do both, send WONT */
6332 if (tn_sopt(WONT,TELOPT_XDISPLOC) < 0)
6334 TELOPT_UNANSWERED_WONT(TELOPT_XDISPLOC) = 1;
6338 sb_out[0] = (CHAR) IAC; /* I Am a Command */
6339 sb_out[1] = (CHAR) SB; /* Subnegotiation */
6340 sb_out[2] = TELOPT_XDISPLOC; /* X-Display Location */
6341 sb_out[3] = (CHAR) 0; /* Is... */
6342 for (i = 4; *disp; disp++,i++) { /* Copy and uppercase it */
6343 sb_out[i] = (char) *disp;
6346 if (deblog || tn_deb || debses) {
6347 sb_out[i] = '\0'; /* For debugging */
6348 ckmakxmsg( tn_msg_out,TN_MSG_LEN,
6349 "TELNET SENT SB ",TELOPT(TELOPT_XDISPLOC),
6350 " IS ",(char *)sb_out+4," IAC SE",
6351 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
6354 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
6355 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
6357 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
6360 debug(F100,tn_msg_out,"",0);
6361 if (tn_deb || debses) tn_debug(tn_msg_out);
6363 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
6365 ReleaseTelnetMutex();
6371 #endif /* CK_XDISPLOC */
6372 #endif /* CK_ENVIRONMENT */
6376 tn_sndfwdx() { /* Send Fwd X Screen number to host */
6377 unsigned char screen = 0;
6381 /* if (!IS_TELNET()) return(0); */
6383 if (!TELOPT_U(TELOPT_FORWARD_X)) return(0);
6385 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6391 * The format of the DISPLAY variable is [<host>:]<display>[.<screen>]
6392 * where <host> is an optional DNS name or ip address with a default of
6393 * the localhost; the screen defaults to 0
6396 disp = (char *)tn_get_display();
6399 colon = ckindex(":",disp,0,0,1);
6400 dot = ckindex(".",&disp[colon],0,0,1);
6403 screen = atoi(&disp[colon+dot]);
6410 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
6411 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
6412 sb_out[i++] = TELOPT_FORWARD_X; /* Forward X */
6413 sb_out[i++] = FWDX_SCREEN; /* Screen */
6414 sb_out[i++] = screen;
6415 if ( screen == IAC )
6417 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
6418 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
6420 if (deblog || tn_deb || debses) {
6421 ckmakxmsg( tn_msg_out,TN_MSG_LEN,
6422 "TELNET SENT SB ",TELOPT(TELOPT_FORWARD_X),
6423 " SCREEN ",ckctox(screen,1)," IAC SE",
6424 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
6428 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
6431 debug(F100,tn_msg_out,"",0);
6432 if (tn_deb || debses) tn_debug(tn_msg_out);
6434 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
6436 ReleaseTelnetMutex();
6442 #endif /* CK_FORWARD_X */
6446 tn_sndloc() { /* Send location. */
6447 int i,rc; /* Worker. */
6450 /* if (!IS_TELNET()) return(0); */
6452 if (!TELOPT_ME(TELOPT_SNDLOC)) return(0);
6455 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6459 ttloc = (tn_loc ? tn_loc : ""); /* In case we are being called even */
6460 /* though there is no location. */
6461 sb_out[0] = (CHAR) IAC; /* I Am a Command */
6462 sb_out[1] = (CHAR) SB; /* Subnegotiation */
6463 sb_out[2] = TELOPT_SNDLOC; /* Location */
6464 for (i = 3; *ttloc && i < TSBUFSIZ; ttloc++,i++) /* Copy it */
6465 sb_out[i] = (char) *ttloc;
6466 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
6467 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
6470 if (deblog || tn_deb || debses) {
6471 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
6472 "TELNET SENT SB ",TELOPT(TELOPT_SNDLOC)," ",(char *)sb_out+3,
6473 " IAC SE", NULL,NULL,NULL,NULL,NULL,NULL,NULL);
6477 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
6480 debug(F100,tn_msg_out,"",0);
6481 if (tn_deb || debses) tn_debug(tn_msg_out);
6483 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
6485 ReleaseTelnetMutex();
6489 sb_out[i-2] = '\0'; /* For debugging */
6492 #endif /* CK_SNDLOC */
6494 #ifdef CK_NAWS /* NAWS = Negotiate About Window Size */
6496 tn_snaws() { /* Send terminal width and height, RFC 1073 */
6498 CHAR sb_out[24]; /* multiple threads */
6501 int x = VscrnGetWidth(VTERM),
6502 y = VscrnGetHeight(VTERM) - (tt_status[VTERM] ? 1 : 0);
6504 int x = tt_cols, y = tt_rows;
6507 if (ttnet != NET_TCPB) return(0);
6508 if (ttnproto != NP_TELNET) return(0);
6509 if (!TELOPT_ME(TELOPT_NAWS)) return(0);
6512 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6519 if (x == TELOPT_SB(TELOPT_NAWS).naws.x && /* Only send if changed */
6520 y == TELOPT_SB(TELOPT_NAWS).naws.y
6523 TELOPT_SB(TELOPT_NAWS).naws.x = x; /* Remember the size */
6524 TELOPT_SB(TELOPT_NAWS).naws.y = y;
6526 sb_out[i++] = (CHAR) IAC; /* Send the subnegotiation */
6527 sb_out[i++] = (CHAR) SB;
6528 sb_out[i++] = TELOPT_NAWS;
6529 sb_out[i++] = (CHAR) (x >> 8) & 0xff;
6530 if ((CHAR) sb_out[i-1] == (CHAR) IAC) /* IAC in data must be doubled */
6531 sb_out[i++] = (CHAR) IAC;
6532 sb_out[i++] = (CHAR) (x & 0xff);
6533 if ((CHAR) sb_out[i-1] == (CHAR) IAC)
6534 sb_out[i++] = (CHAR) IAC;
6535 sb_out[i++] = (CHAR) (y >> 8) & 0xff;
6536 if ((CHAR) sb_out[i-1] == (CHAR) IAC)
6537 sb_out[i++] = (CHAR) IAC;
6538 sb_out[i++] = (CHAR) (y & 0xff);
6539 if ((CHAR) sb_out[i-1] == (CHAR) IAC)
6540 sb_out[i++] = (CHAR) IAC;
6541 sb_out[i++] = (CHAR) IAC;
6542 sb_out[i++] = (CHAR) SE;
6544 if (deblog || tn_deb || debses) {
6545 ckmakxmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB NAWS ",
6546 ckitoa(x)," ",ckitoa(y)," IAC SE",
6547 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
6551 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
6554 debug(F100,tn_msg_out,"",0);
6555 if (tn_deb || debses) tn_debug(tn_msg_out);
6557 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
6559 ReleaseTelnetMutex();
6563 #endif /* NOLOCAL */
6566 #endif /* CK_NAWS */
6569 static char * tnc_signature = NULL;
6570 static int tnc_ls_mask = 0;
6571 static int tnc_ls = 0;
6572 static int tnc_ms_mask = 255;
6573 static int tnc_ms = 0;
6574 static int tnc_oflow = 0;
6575 static int tnc_iflow = 0;
6576 static int tnc_bps = 0;
6577 static int tnc_datasize = 0;
6578 static int tnc_parity = 0;
6579 static int tnc_stopbit = 0;
6580 static int tnc_break = 0;
6581 static int tnc_dtr = 0;
6582 static int tnc_rts = 0;
6583 static int tnc_suspend_xmit = 0;
6584 static int tnc_bps_index = -1;
6589 #else /* CK_ANSIC */
6591 #endif /* CK_ANSIC */
6593 debug(F100,"tnc_init","",0);
6595 /* if (!IS_TELNET()) return(0); */
6597 if (tnc_signature) {
6598 free(tnc_signature);
6599 tnc_signature = NULL;
6614 tnc_suspend_xmit = 0;
6622 #else /* CK_ANSIC */
6624 #endif /* CK_ANSIC */
6625 /* tn_sndcomport */ {
6626 int baud, datasize, parity, stopsize, oflow, iflow;
6627 CONST char * signature;
6629 /* if (!IS_TELNET()) return(0); */
6631 debug(F100,"tnc_sndcomport","",0);
6632 signature = tnc_get_signature();
6633 baud = tnc_get_baud();
6634 datasize = tnc_get_datasize();
6635 parity = tnc_get_parity();
6636 stopsize = tnc_get_stopsize();
6637 oflow = tnc_get_oflow();
6638 iflow = tnc_get_iflow();
6639 tnc_set_ls_mask(255);
6640 tnc_set_ms_mask(255);
6646 tnc_wait(CHAR * msg, int ms)
6647 #else /* CK_ANSIC */
6648 tnc_wait(msg, ms) CHAR * msg; int ms;
6649 #endif /* CK_ANSIC */
6651 int rc, tn_wait_save = tn_wait_flg;
6653 /* if (!IS_TELNET()) return(0); */
6655 debug(F111,"tnc_wait","begin",ms);
6657 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms = 1;
6659 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 1;
6661 rc = tn_wait((char *)msg);
6663 debug(F110,"tnc_wait","end",0);
6664 tn_wait_flg = tn_wait_save;
6668 /* Returns -1 on error, 0 on success */
6669 /* In order for this code to work, sb[len] == IAC */
6673 tnc_tn_sb(CHAR * sb, int len)
6675 tnc_tn_sb(sb, len) CHAR * sb; int len;
6676 #endif /* CK_ANSIC */
6678 if (ttnet != NET_TCPB) return(0);
6679 if (ttnproto != NP_TELNET) return(0);
6680 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
6682 if (!sb) return(-1);
6685 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6690 debug(F111,"tnc_tn_sb","sb[0]",sb[0]);
6691 debug(F111,"tnc_tn_sb","len",len);
6694 case TNC_C2S_SIGNATURE:
6695 case TNC_S2C_SIGNATURE:
6696 debug(F111,"tnc_tn_sb","signature",len);
6698 tnc_send_signature("Kermit Telnet Com Port Option");
6700 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6702 free(tnc_signature);
6703 tnc_signature = malloc(len);
6704 if (tnc_signature) {
6705 memcpy(tnc_signature,&sb[1],len-1);
6706 tnc_signature[len-1] = '\0';
6711 case TNC_C2S_SET_BAUDRATE:
6712 case TNC_S2C_SET_BAUDRATE: {
6714 char * br = (char *)&baudrate;
6715 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6717 /* Actual behavior of the Access Server... */
6718 debug(F111,"tnc_tn_sb","baudrate index",sb[1]);
6754 case TNC_BPS_115200:
6757 case TNC_BPS_230400:
6760 case TNC_BPS_460800:
6766 } else if (len == 5) {
6767 /* This section attempts to follow RFC 2217 */
6774 /* AOS/VS doesn't have ntohl() but MV's are big-endian */
6777 tnc_bps = ntohl(baudrate);
6778 #endif /* datageneral */
6779 debug(F111,"tnc_tn_sb","baudrate rfc",tnc_bps);
6781 debug(F111,"tnc_tn_sb","baudrate invalid len",len);
6786 case TNC_C2S_SET_DATASIZE:
6787 case TNC_S2C_SET_DATASIZE:
6788 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6791 tnc_datasize = sb[1];
6792 debug(F111,"tnc_tn_sb","datasize",sb[1]);
6795 case TNC_C2S_SET_PARITY:
6796 case TNC_S2C_SET_PARITY:
6797 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6801 debug(F111,"tnc_tn_sb","parity",sb[1]);
6804 case TNC_C2S_SET_STOPSIZE:
6805 case TNC_S2C_SET_STOPSIZE:
6806 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6809 tnc_stopbit = sb[1];
6810 debug(F111,"tnc_tn_sb","stopsize",sb[1]);
6813 case TNC_C2S_SET_CONTROL:
6814 case TNC_S2C_SET_CONTROL:
6816 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6821 /* This line should be removed when testing is complete. */
6822 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6823 #endif /* COMMENT */
6826 case TNC_CTL_OFLOW_REQUEST:
6827 /* determine local outbound flow control and send to peer */
6828 /* Cisco IOS returns 0 (TNC_CTL_OFLOW_REQUEST) when attempting */
6829 /* to set the inbound flow control if it is not supported */
6830 /* separately from outbound flow control. So must reset */
6831 /* wait for sb flag. */
6832 debug(F110,"tnc_tn_sb","oflow request",0);
6833 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6835 case TNC_CTL_OFLOW_NONE:
6836 case TNC_CTL_OFLOW_XON_XOFF:
6837 case TNC_CTL_OFLOW_RTS_CTS:
6838 case TNC_CTL_OFLOW_DCD:
6839 case TNC_CTL_OFLOW_DSR:
6840 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6842 debug(F111,"tnc_tn_sb","oflow",sb[1]);
6844 case TNC_CTL_BREAK_REQUEST:
6845 /* determine local break state and send to peer */
6846 debug(F110,"tnc_tn_sb","break request",0);
6848 case TNC_CTL_BREAK_ON:
6849 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6851 debug(F110,"tnc_tn_sb","break on",0);
6854 case TNC_CTL_BREAK_OFF:
6855 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6857 debug(F110,"tnc_tn_sb","break off",0);
6860 case TNC_CTL_DTR_REQUEST:
6861 /* determine local dtr state and send to peer */
6862 debug(F110,"tnc_tn_sb","dtr request",0);
6865 case TNC_CTL_DTR_ON:
6866 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6868 debug(F110,"tnc_tn_sb","dtr on",0);
6871 case TNC_CTL_DTR_OFF:
6872 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6874 debug(F110,"tnc_tn_sb","dtr off",0);
6877 case TNC_CTL_RTS_REQUEST:
6878 /* determine local rts state and send to peer */
6879 debug(F110,"tnc_tn_sb","rts request",0);
6882 case TNC_CTL_RTS_ON:
6883 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6885 debug(F110,"tnc_tn_sb","rts on",0);
6888 case TNC_CTL_RTS_OFF:
6889 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6891 debug(F110,"tnc_tn_sb","rts off",0);
6894 case TNC_CTL_IFLOW_REQUEST:
6895 /* determine local inbound flow control and send to peer */
6896 debug(F110,"tnc_tn_sb","iflow request",0);
6899 case TNC_CTL_IFLOW_NONE:
6900 case TNC_CTL_IFLOW_XON_XOFF:
6901 case TNC_CTL_IFLOW_RTS_CTS:
6902 case TNC_CTL_IFLOW_DTR:
6903 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6905 debug(F111,"tnc_tn_sb","iflow",sb[1]);
6912 case TNC_C2S_NOTIFY_LINESTATE:
6913 case TNC_S2C_SEND_LS:
6917 debug(F111,"tnc_tn_sb","linestate",sb[1]);
6918 if (tn_deb || debses) {
6919 if (tnc_ls & TNC_MS_DATA_READY )
6920 tn_debug(" ComPort Linestate Data Ready");
6921 if (tnc_ls & TNC_MS_OVERRUN_ERROR )
6922 tn_debug(" ComPort Linestate Overrun Error");
6923 if (tnc_ls & TNC_MS_PARITY_ERROR )
6924 tn_debug(" ComPort Linestate Parity Error");
6925 if (tnc_ls & TNC_MS_FRAME_ERROR )
6926 tn_debug(" ComPort Linestate Framing Error");
6927 if (tnc_ls & TNC_MS_BREAK_ERROR )
6928 tn_debug(" ComPort Linestate Break Detect Error");
6929 if (tnc_ls & TNC_MS_HR_EMPTY )
6930 tn_debug(" ComPort Linestate Holding Register Empty");
6931 if (tnc_ls & TNC_MS_SR_EMPTY )
6932 tn_debug(" ComPort Linestate Shift Register Empty");
6933 if (tnc_ls & TNC_MS_TIMEOUT_ERROR )
6934 tn_debug(" ComPort Linestate Timeout Error");
6938 case TNC_C2S_NOTIFY_MODEMSTATE:
6939 case TNC_S2C_SEND_MS:
6940 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms = 0;
6944 debug(F111,"tnc_tn_sb","modemstate",sb[1]);
6945 if (tn_deb || debses) {
6946 if (tnc_ms & TNC_MS_CTS_DELTA )
6947 tn_debug(" ComPort Modemstate CTS State Change");
6948 if (tnc_ms & TNC_MS_DSR_DELTA )
6949 tn_debug(" ComPort Modemstate DSR State Change");
6950 if (tnc_ms & TNC_MS_EDGE_RING )
6951 tn_debug(" ComPort Modemstate Trailing Edge Ring Detector On");
6953 tn_debug(" ComPort Modemstate Trailing Edge Ring Detector Off");
6954 if (tnc_ms & TNC_MS_RLSD_DELTA )
6955 tn_debug(" ComPort Modemstate RLSD State Change");
6956 if (tnc_ms & TNC_MS_CTS_SIG )
6957 tn_debug(" ComPort Modemstate CTS Signal On");
6959 tn_debug(" ComPort Modemstate CTS Signal Off");
6960 if (tnc_ms & TNC_MS_DSR_SIG )
6961 tn_debug(" ComPort Modemstate DSR Signal On");
6963 tn_debug(" ComPort Modemstate DSR Signal Off");
6964 if (tnc_ms & TNC_MS_RI_SIG )
6965 tn_debug(" ComPort Modemstate Ring Indicator On");
6967 tn_debug(" ComPort Modemstate Ring Indicator Off");
6968 if (tnc_ms & TNC_MS_RLSD_SIG )
6969 tn_debug(" ComPort Modemstate RLSD Signal On");
6971 tn_debug(" ComPort Modemstate RLSD Signal Off");
6975 case TNC_C2S_FLOW_SUSPEND:
6976 case TNC_S2C_FLOW_SUSPEND:
6977 debug(F110,"tnc_tn_sb","flow suspend",0);
6978 tnc_suspend_xmit = 1;
6981 case TNC_C2S_FLOW_RESUME:
6982 case TNC_S2C_FLOW_RESUME:
6983 debug(F110,"tnc_tn_sb","flow resume",0);
6984 tnc_suspend_xmit = 0;
6987 case TNC_C2S_SET_LS_MASK:
6988 case TNC_S2C_SET_LS_MASK:
6989 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6992 debug(F111,"tnc_tn_sb","linestate mask",sb[1]);
6993 tnc_ls_mask = sb[1];
6996 case TNC_C2S_SET_MS_MASK:
6997 case TNC_S2C_SET_MS_MASK:
6998 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
7001 debug(F111,"tnc_tn_sb","modemstate mask",sb[1]);
7002 tnc_ls_mask = sb[1];
7009 debug(F111,"tnc_tn_sb","purge",sb[1]);
7011 case TNC_PURGE_RECEIVE:
7012 case TNC_PURGE_TRANSMIT:
7013 case TNC_PURGE_BOTH:
7014 /* purge local buffers */
7028 tnc_get_signature(void)
7029 #else /* CK_ANSIC */
7031 #endif /* CK_ANSIC */
7032 /* tnc_get_signature */ {
7033 /* send IAC SB COM-PORT SIGNATURE IAC SE */
7034 /* wait for response */
7037 if (ttnet != NET_TCPB) return(NULL);
7038 if (ttnproto != NP_TELNET) return(NULL);
7040 if (!TELOPT_ME(TELOPT_COMPORT)) return(NULL);
7043 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7048 if ( tnc_signature )
7049 return(tnc_signature);
7051 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7052 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7053 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7054 sb_out[i++] = TNC_C2S_SIGNATURE; /* Signature */
7055 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7056 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7059 if (deblog || tn_deb || debses) {
7060 ckmakmsg(tn_msg_out,TN_MSG_LEN,
7061 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7062 " SIGNATURE IAC SE", NULL);
7066 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7069 debug(F100,tn_msg_out,"",0);
7070 if (tn_deb || debses) tn_debug(tn_msg_out);
7072 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7074 ReleaseTelnetMutex();
7079 if (tnc_wait((CHAR *)"comport signature request",0) < 0) {
7083 debug(F110,"tnc_get_signature",tnc_signature,0);
7084 return(tnc_signature);
7089 tnc_send_signature(char * signature)
7090 #else /* CK_ANSIC */
7091 tnc_send_signature(signature) char * signature;
7092 #endif /* CK_ANSIC */
7093 /* tnc_send_signature */ {
7094 /* send IAC SB COM-PORT SIGNATURE <text> IAC SE */
7095 int i = 0, j = 0, rc;
7097 debug(F110,"tnc_send_signature",signature,0);
7099 if (!signature || !signature[0])
7102 if (ttnet != NET_TCPB) return(0);
7103 if (ttnproto != NP_TELNET) return(0);
7105 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7108 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7113 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7114 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7115 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7116 sb_out[i++] = TNC_C2S_SIGNATURE; /* Signature */
7117 for (; signature[j]; i++,j++)
7118 sb_out[i] = signature[j];
7119 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7120 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7123 if (deblog || tn_deb || debses) {
7124 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7125 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7126 " SIGNATURE ", signature, " IAC SE", NULL,
7127 NULL,NULL,NULL,NULL,NULL,NULL);
7131 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7134 debug(F100,tn_msg_out,"",0);
7135 if (tn_deb || debses) tn_debug(tn_msg_out);
7137 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7139 ReleaseTelnetMutex();
7148 tnc_set_baud( long baud )
7149 #else /* CK_ANSIC */
7150 tnc_set_baud(baud) long baud;
7151 #endif /* CK_ANSIC */
7152 /* tnc_set_baud */ {
7153 /* send IAC SB COM-PORT SET-BAUD <value(4)> IAC SE */
7154 /* wait for response */
7155 /* 0 is used to request the current baud rate and */
7156 /* may not be sent by this func */
7157 /* return new host value */
7160 * the above comes from the RFC. But that is not what I am seeing
7161 * instead I appear to be seeing to following:
7184 /* AOS/VS doesn't have htonl() but MV's are big-endian */
7185 long net_baud = baud;
7187 long net_baud = htonl(baud);
7188 #endif /* datageneral */
7191 debug(F111,"tnc_set_baud","begin",baud);
7193 if (ttnet != NET_TCPB) return(0);
7194 if (ttnproto != NP_TELNET) return(0);
7196 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7199 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7207 if ( net_baud != 0 && net_baud == tnc_bps)
7210 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7211 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7212 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7213 sb_out[i++] = TNC_C2S_SET_BAUDRATE; /* Set Baud Rate */
7215 if (tnc_bps_index) {
7216 /* IOS Access Server */
7219 else if (baud <= 600)
7221 else if (baud <= 1200)
7223 else if (baud <= 2400)
7225 else if (baud <= 4800)
7227 else if (baud <= 9600)
7229 else if (baud <= 14400)
7231 else if (baud <= 19200)
7233 else if (baud <= 28800)
7235 else if (baud <= 38400)
7237 else if (baud <= 57600)
7239 else if (baud <= 115200)
7241 else if (baud <= 230400)
7248 sb_out[i++] = ((char *)&net_baud)[0];
7249 sb_out[i++] = ((char *)&net_baud)[1];
7250 sb_out[i++] = ((char *)&net_baud)[2];
7251 sb_out[i++] = ((char *)&net_baud)[3];
7253 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7254 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7257 if (deblog || tn_deb || debses) {
7258 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7259 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7260 " SET-BAUD-RATE ", ckltoa(baud)," IAC SE", NULL,
7261 NULL,NULL,NULL,NULL,NULL,NULL);
7266 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7269 debug(F100,tn_msg_out,"",0);
7270 if (tn_deb || debses) tn_debug(tn_msg_out);
7272 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7274 ReleaseTelnetMutex();
7279 if (tnc_wait((CHAR *)"comport set baud rate",0) < 0) {
7283 debug(F111,"tnc_set_baud","end",tnc_bps);
7290 #else /* CK_ANSIC */
7292 #endif /* CK_ANSIC */
7293 /* tnc_get_baud */ {
7294 /* send IAC SB COM-PORT SET-BAUD <value(4)=0> IAC SE */
7295 /* wait for response */
7298 debug(F110,"tnc_get_baud","begin",0);
7300 if (ttnet != NET_TCPB) return(0);
7301 if (ttnproto != NP_TELNET) return(0);
7303 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7306 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7311 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7312 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7313 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7314 sb_out[i++] = TNC_C2S_SET_BAUDRATE; /* Set Baud Rate */
7316 if (tnc_bps_index > 0) {
7326 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7327 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7330 if (deblog || tn_deb || debses) {
7331 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7332 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7333 " SET-BAUD-RATE ", ckltoa(0)," IAC SE", NULL,
7334 NULL,NULL,NULL,NULL,NULL,NULL);
7338 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7341 debug(F100,tn_msg_out,"",0);
7342 if (tn_deb || debses) tn_debug(tn_msg_out);
7344 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7346 ReleaseTelnetMutex();
7351 if (tnc_wait((CHAR *)"comport get baud rate",0) < 0) {
7355 debug(F111,"tnc_get_baud","end",tnc_bps);
7361 tnc_set_datasize(int datasize)
7362 #else /* CK_ANSIC */
7363 tnc_set_datasize(datasize) int datasize;
7364 #endif /* CK_ANSIC */
7365 /* tnc_set_datasize */ {
7366 /* IAC SB COM-PORT SET_DATASIZE <value(1)> IAC SE */
7367 /* Valid <value>s are 5 through 8 */
7368 /* Wait for response */
7369 /* return new host value */
7373 debug(F111,"tnc_set_datasize","begin",datasize);
7375 if (ttnet != NET_TCPB) return(0);
7376 if (ttnproto != NP_TELNET) return(0);
7378 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7381 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7386 if ( !(datasize >= 5 && datasize <= 8) )
7389 if ( datasize != 0 && datasize == tnc_datasize )
7390 return(tnc_datasize);
7392 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7393 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7394 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7395 sb_out[i++] = TNC_C2S_SET_DATASIZE; /* Set DataSize */
7396 sb_out[i++] = (unsigned char)(datasize & 0xFF);
7397 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7398 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7401 if (deblog || tn_deb || debses) {
7402 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7403 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7404 " SET-DATASIZE ", ckitoa(datasize)," IAC SE", NULL,
7405 NULL,NULL,NULL,NULL,NULL,NULL);
7409 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7412 debug(F100,tn_msg_out,"",0);
7413 if (tn_deb || debses) tn_debug(tn_msg_out);
7415 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7417 ReleaseTelnetMutex();
7422 if (tnc_wait((CHAR *)"comport set datasize",0) < 0) {
7426 debug(F111,"tnc_set_datasize","end",tnc_datasize);
7427 return(tnc_datasize);
7432 tnc_get_datasize(void)
7433 #else /* CK_ANSIC */
7435 #endif /* CK_ANSIC */
7436 /* tnc_get_datasize */ {
7437 /* IAC SB COM-PORT SET_DATASIZE <value(1)=0> IAC SE */
7438 /* Wait for response */
7441 debug(F110,"tnc_get_datasize","begin",0);
7443 if (ttnet != NET_TCPB) return(0);
7444 if (ttnproto != NP_TELNET) return(0);
7446 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7449 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7454 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7455 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7456 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7457 sb_out[i++] = TNC_C2S_SET_DATASIZE; /* Set DataSize */
7459 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7460 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7463 if (deblog || tn_deb || debses) {
7464 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7465 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7466 " SET-DATASIZE ", ckltoa(0)," IAC SE", NULL,
7467 NULL,NULL,NULL,NULL,NULL,NULL);
7471 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7474 debug(F100,tn_msg_out,"",0);
7475 if (tn_deb || debses) tn_debug(tn_msg_out);
7477 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7479 ReleaseTelnetMutex();
7484 if (tnc_wait((CHAR *)"comport get datasize",0) < 0) {
7488 debug(F111,"tnc_get_datasize","end",tnc_datasize);
7489 return(tnc_datasize);
7494 tnc_set_parity(int parity)
7495 #else /* CK_ANSIC */
7496 tnc_set_parity(parity) int parity;
7497 #endif /* CK_ANSIC */
7498 /* tnc_set_parity */ {
7499 /* IAC SB COM-PORT SET_PARITY <value(1)> IAC SE */
7507 /* Wait for response. Return new host value. */
7510 debug(F110,"tnc_set_parity","begin",parity);
7512 if (ttnet != NET_TCPB) return(0);
7513 if (ttnproto != NP_TELNET) return(0);
7515 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7518 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7523 if ( !(parity >= 1 && parity <= 5) )
7526 if ( parity != 0 && parity == tnc_parity )
7529 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7530 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7531 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7532 sb_out[i++] = TNC_C2S_SET_PARITY; /* Set Parity */
7533 sb_out[i++] = (unsigned char)(parity & 0xFF);
7534 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7535 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7538 if (deblog || tn_deb || debses) {
7539 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7540 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7541 " SET-PARITY ", ckitoa(parity)," IAC SE", NULL,
7542 NULL,NULL,NULL,NULL,NULL,NULL);
7546 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7549 debug(F100,tn_msg_out,"",0);
7550 if (tn_deb || debses) tn_debug(tn_msg_out);
7552 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7554 ReleaseTelnetMutex();
7559 if (tnc_wait((CHAR *)"comport set parity",0) < 0) {
7563 debug(F111,"tnc_set_parity","end",tnc_parity);
7569 tnc_get_parity(void)
7570 #else /* CK_ANSIC */
7572 #endif /* CK_ANSIC */
7573 /* tnc_get_parity */ {
7574 /* IAC SB COM-PORT SET_PARITY <value(1)=0> IAC SE */
7575 /* wait for response */
7578 debug(F110,"tnc_get_parity","begin",0);
7579 if (ttnet != NET_TCPB) return(0);
7580 if (ttnproto != NP_TELNET) return(0);
7582 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7585 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7590 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7591 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7592 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7593 sb_out[i++] = TNC_C2S_SET_PARITY; /* Set Parity */
7595 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7596 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7599 if (deblog || tn_deb || debses) {
7600 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7601 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7602 " SET-PARITY ", ckitoa(0)," IAC SE", NULL,
7603 NULL,NULL,NULL,NULL,NULL,NULL);
7607 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7610 debug(F100,tn_msg_out,"",0);
7611 if (tn_deb || debses) tn_debug(tn_msg_out);
7613 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7615 ReleaseTelnetMutex();
7620 if (tnc_wait((CHAR *)"comport get parity",0) < 0) {
7624 debug(F111,"tnc_get_parity","end",tnc_parity);
7630 tnc_set_stopsize(int stopsize)
7631 #else /* CK_ANSIC */
7632 tnc_set_stopsize(stopsize) int stopsize;
7633 #endif /* CK_ANSIC */
7634 /* tnc_set_stopsize */ {
7635 /* IAC SB COM-PORT SET_STOPSIZE <value(1)> IAC SE */
7636 /* Value Stop Bit Size
7641 /* Wait for response. Return new host value. */
7644 debug(F111,"tnc_set_stopsize","begin",stopsize);
7645 if (ttnet != NET_TCPB) return(0);
7646 if (ttnproto != NP_TELNET) return(0);
7648 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7651 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7656 if (!(stopsize >= 1 && stopsize <= 3) )
7659 if ( stopsize != 0 && stopsize == tnc_stopbit )
7660 return(tnc_stopbit);
7662 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7663 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7664 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7665 sb_out[i++] = TNC_C2S_SET_STOPSIZE; /* Set Stop Bits */
7666 sb_out[i++] = (unsigned char)(stopsize & 0xFF);
7667 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7668 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7671 if (deblog || tn_deb || debses) {
7672 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7673 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7674 " SET-STOPSIZE ", ckitoa(stopsize)," IAC SE", NULL,
7675 NULL,NULL,NULL,NULL,NULL,NULL);
7679 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7682 debug(F100,tn_msg_out,"",0);
7683 if (tn_deb || debses) tn_debug(tn_msg_out);
7685 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7687 ReleaseTelnetMutex();
7692 if (tnc_wait((CHAR *)"comport set stopsize",0) < 0) {
7696 debug(F111,"tnc_set_stopsize","end",tnc_stopbit);
7697 return(tnc_stopbit);
7702 tnc_get_stopsize(void)
7703 #else /* CK_ANSIC */
7705 #endif /* CK_ANSIC */
7706 /* tnc_get_stopsize */ {
7707 /* IAC SB COM-PORT SET_STOPSIZE <value(1)=0> IAC SE */
7708 /* Wait for response */
7711 debug(F110,"tnc_get_stopsize","begin",0);
7712 if (ttnet != NET_TCPB) return(0);
7713 if (ttnproto != NP_TELNET) return(0);
7715 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7718 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7723 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7724 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7725 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7726 sb_out[i++] = TNC_C2S_SET_STOPSIZE; /* Set Stop Bits */
7728 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7729 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7732 if (deblog || tn_deb || debses) {
7733 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7734 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7735 " SET-STOPSIZE ", ckitoa(0)," IAC SE", NULL,
7736 NULL,NULL,NULL,NULL,NULL,NULL);
7740 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7743 debug(F100,tn_msg_out,"",0);
7744 if (tn_deb || debses) tn_debug(tn_msg_out);
7746 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7748 ReleaseTelnetMutex();
7753 if (tnc_wait((CHAR *)"comport set stopsize",0) < 0) {
7757 debug(F111,"tnc_get_stopsize","end",tnc_stopbit);
7758 return(tnc_stopbit);
7763 tnc_set_oflow(int control)
7764 #else /* CK_ANSIC */
7765 tnc_set_oflow(control) int control;
7766 #endif /* CK_ANSIC */
7767 /* tnc_set_oflow */ {
7768 /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
7769 /* Value Flow Control
7776 /* wait for response, return new host value. */
7779 debug(F111,"tnc_set_oflow","begin",control);
7780 if (ttnet != NET_TCPB) return(0);
7781 if (ttnproto != NP_TELNET) return(0);
7783 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7786 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7791 if (control != 1 && control != 2 && control != 3 &&
7792 control != 17 && control != 19)
7795 if ( control != 0 && control == tnc_oflow )
7798 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7799 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7800 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7801 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
7802 sb_out[i++] = (unsigned char)(control & 0xFF);
7803 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7804 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7807 if (deblog || tn_deb || debses) {
7808 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7809 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7810 " SET-CONTROL ", ckitoa(control)," IAC SE", NULL,
7811 NULL,NULL,NULL,NULL,NULL,NULL);
7815 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7818 debug(F100,tn_msg_out,"",0);
7819 if (tn_deb || debses) tn_debug(tn_msg_out);
7821 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7823 ReleaseTelnetMutex();
7828 if (tnc_wait((CHAR *)"comport set outbound flow control",0) < 0) {
7832 debug(F111,"tnc_set_oflow","end",tnc_oflow);
7839 #else /* CK_ANSIC */
7841 #endif /* CK_ANSIC */
7842 /* tnc_get_oflow */ {
7843 /* IAC SB COM_PORT SET_CONTROL <value(1)=0> IAC SE */
7844 /* wait for response */
7847 debug(F110,"tnc_get_oflow","begin",0);
7848 if (ttnet != NET_TCPB) return(0);
7849 if (ttnproto != NP_TELNET) return(0);
7851 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7854 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7859 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7860 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7861 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7862 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
7863 sb_out[i++] = TNC_CTL_OFLOW_REQUEST;
7864 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7865 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7868 if (deblog || tn_deb || debses) {
7869 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7870 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7872 ckitoa(TNC_CTL_OFLOW_REQUEST),
7874 NULL,NULL,NULL,NULL,NULL,NULL);
7878 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7881 debug(F100,tn_msg_out,"",0);
7882 if (tn_deb || debses) tn_debug(tn_msg_out);
7884 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7886 ReleaseTelnetMutex();
7891 if (tnc_wait((CHAR *)"comport get outbound flow control",0) < 0) {
7895 debug(F111,"tnc_get_oflow","end",tnc_oflow);
7901 tnc_set_iflow(int control)
7902 #else /* CK_ANSIC */
7903 tnc_set_iflow(control) int control;
7904 #endif /* CK_ANSIC */
7905 /* tnc_set_iflow */ {
7906 /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
7907 /* Value Flow Control
7908 * 14 No Flow Control
7913 /* wait for response, return new host value. */
7916 debug(F111,"tnc_set_iflow","begin",control);
7917 if (ttnet != NET_TCPB) return(0);
7918 if (ttnproto != NP_TELNET) return(0);
7920 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7923 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7928 if (control != 14 && control != 15 && control != 16 && control != 18)
7931 if ( control != 0 && control == tnc_iflow )
7934 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7935 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7936 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7937 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
7938 sb_out[i++] = (unsigned char)(control & 0xFF);
7939 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7940 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7943 if (deblog || tn_deb || debses) {
7944 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7945 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7946 " SET-CONTROL ", ckitoa(control)," IAC SE", NULL,
7947 NULL,NULL,NULL,NULL,NULL,NULL);
7951 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7954 debug(F100,tn_msg_out,"",0);
7955 if (tn_deb || debses) tn_debug(tn_msg_out);
7957 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7959 ReleaseTelnetMutex();
7964 if (tnc_wait((CHAR *)"comport set inbound flow control",0) < 0) {
7968 debug(F111,"tnc_set_iflow","end",tnc_iflow);
7975 #else /* CK_ANSIC */
7977 #endif /* CK_ANSIC */
7978 /* tnc_get_iflow */ {
7979 /* IAC SB COM_PORT SET_CONTROL <value(1)=13> IAC SE */
7980 /* wait for response */
7983 debug(F110,"tnc_get_iflow","begin",0);
7984 if (ttnet != NET_TCPB) return(0);
7985 if (ttnproto != NP_TELNET) return(0);
7987 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7990 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7995 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7996 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7997 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7998 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
7999 sb_out[i++] = TNC_CTL_IFLOW_REQUEST;
8000 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8001 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8004 if (deblog || tn_deb || debses) {
8005 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8006 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8008 ckitoa(TNC_CTL_IFLOW_REQUEST),
8010 NULL,NULL,NULL,NULL,NULL,NULL);
8014 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8017 debug(F100,tn_msg_out,"",0);
8018 if (tn_deb || debses) tn_debug(tn_msg_out);
8020 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8022 ReleaseTelnetMutex();
8027 if (tnc_wait((CHAR *)"comport get inbound flow control",0) < 0) {
8031 debug(F111,"tnc_get_iflow","end",tnc_iflow);
8037 tnc_set_break_state(int onoff)
8038 #else /* CK_ANSIC */
8039 tnc_set_break_state(onoff) int onoff;
8040 #endif /* CK_ANSIC */
8041 /* tnc_set_break_state */ {
8042 /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
8043 /* Value Break State
8047 /* wait for response, return new host value. */
8050 debug(F111,"tnc_set_break_state","begin",onoff);
8051 if (ttnet != NET_TCPB) return(0);
8052 if (ttnproto != NP_TELNET) return(0);
8054 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8057 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8062 if ( onoff != 0 && onoff == tnc_break )
8065 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8066 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8067 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8068 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8069 sb_out[i++] = onoff ?
8070 TNC_CTL_BREAK_ON : TNC_CTL_BREAK_OFF;
8071 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8072 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8075 if (deblog || tn_deb || debses) {
8076 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8077 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8079 onoff ? "BREAK-ON" : "BREAK-OFF",
8081 NULL,NULL,NULL,NULL,NULL,NULL);
8085 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8088 debug(F100,tn_msg_out,"",0);
8089 if (tn_deb || debses) tn_debug(tn_msg_out);
8091 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8093 ReleaseTelnetMutex();
8098 if (tnc_wait((CHAR *)"comport set break state",0) < 0) {
8102 debug(F111,"tnc_set_break_state","end",tnc_break);
8108 tnc_get_break_state(void)
8109 #else /* CK_ANSIC */
8110 tnc_get_break_state()
8111 #endif /* CK_ANSIC */
8112 /* tnc_get_break_state */ {
8113 /* IAC SB COM_PORT SET_CONTROL <value(1)=4> IAC SE */
8114 /* wait for response */
8117 debug(F110,"tnc_get_break_state","begin",0);
8118 if (ttnet != NET_TCPB) return(0);
8119 if (ttnproto != NP_TELNET) return(0);
8121 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8124 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8129 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8130 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8131 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8132 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8133 sb_out[i++] = TNC_CTL_BREAK_REQUEST;
8134 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8135 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8138 if (deblog || tn_deb || debses) {
8139 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8140 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8144 NULL,NULL,NULL,NULL,NULL,NULL);
8148 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8151 debug(F100,tn_msg_out,"",0);
8152 if (tn_deb || debses) tn_debug(tn_msg_out);
8154 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8156 ReleaseTelnetMutex();
8161 if (tnc_wait((CHAR *)"comport get break state",0) < 0) {
8165 debug(F111,"tnc_get_break_state","end",tnc_break);
8171 tnc_set_dtr_state(int onoff)
8172 #else /* CK_ANSIC */
8173 tnc_set_dtr_state(onoff) int onoff;
8174 #endif /* CK_ANSIC */
8175 /* tnc_set_dtr_state */ {
8176 /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
8181 /* wait for response, return new host value. */
8184 debug(F111,"tnc_set_dtr_state","begin",onoff);
8185 if (ttnet != NET_TCPB) return(0);
8186 if (ttnproto != NP_TELNET) return(0);
8188 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8191 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8196 if ( onoff != 0 && onoff == tnc_dtr )
8199 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8200 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8201 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8202 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8203 sb_out[i++] = onoff ?
8204 TNC_CTL_DTR_ON : TNC_CTL_DTR_OFF;
8205 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8206 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8209 if (deblog || tn_deb || debses) {
8210 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8211 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8213 onoff ? "DTR-ON" : "DTR-OFF",
8215 NULL,NULL,NULL,NULL,NULL,NULL);
8219 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8222 debug(F100,tn_msg_out,"",0);
8223 if (tn_deb || debses) tn_debug(tn_msg_out);
8225 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8227 ReleaseTelnetMutex();
8232 if (tnc_wait((CHAR *)"comport set dtr state",0) < 0) {
8236 debug(F111,"tnc_set_dtr_state","end",tnc_dtr);
8242 tnc_get_dtr_state(void)
8243 #else /* CK_ANSIC */
8245 #endif /* CK_ANSIC */
8246 /* tnc_get_dtr_state */ {
8247 /* IAC SB COM_PORT SET_CONTROL <value(1)=7> IAC SE */
8248 /* wait for response */
8251 debug(F110,"tnc_get_dtr_state","begin",0);
8252 if (ttnet != NET_TCPB) return(0);
8253 if (ttnproto != NP_TELNET) return(0);
8255 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8258 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8263 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8264 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8265 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8266 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8267 sb_out[i++] = TNC_CTL_DTR_REQUEST;
8268 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8269 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8272 if (deblog || tn_deb || debses) {
8273 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8274 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8278 NULL,NULL,NULL,NULL,NULL,NULL);
8282 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8285 debug(F100,tn_msg_out,"",0);
8286 if (tn_deb || debses) tn_debug(tn_msg_out);
8288 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8290 ReleaseTelnetMutex();
8295 if (tnc_wait((CHAR *)"comport get dtr state",0) < 0) {
8299 debug(F111,"tnc_get_dtr_state","end",tnc_dtr);
8305 tnc_set_rts_state(int onoff)
8306 #else /* CK_ANSIC */
8307 tnc_set_rts_state(onoff) int onoff;
8308 #endif /* CK_ANSIC */
8309 /* tnc_set_rts_state */ {
8310 /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
8315 /* wait for response, return new host value. */
8318 debug(F111,"tnc_set_rts_state","begin",onoff);
8319 if (ttnet != NET_TCPB) return(0);
8320 if (ttnproto != NP_TELNET) return(0);
8322 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8325 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8330 if ( onoff != 0 && onoff == tnc_rts )
8333 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8334 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8335 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8336 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8337 sb_out[i++] = onoff ?
8338 TNC_CTL_RTS_ON : TNC_CTL_RTS_OFF;
8339 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8340 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8343 if (deblog || tn_deb || debses) {
8344 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8345 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8347 onoff ? "RTS-ON" : "RTS-OFF",
8349 NULL,NULL,NULL,NULL,NULL,NULL);
8353 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8356 debug(F100,tn_msg_out,"",0);
8357 if (tn_deb || debses) tn_debug(tn_msg_out);
8359 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8361 ReleaseTelnetMutex();
8366 if (tnc_wait((CHAR *)"comport set rts state",0) < 0) {
8370 debug(F111,"tnc_set_rts_state","end",tnc_rts);
8376 tnc_get_rts_state(void)
8377 #else /* CK_ANSIC */
8379 #endif /* CK_ANSIC */
8380 /* tnc_get_rts_state */ {
8381 /* IAC SB COM_PORT SET_CONTROL <value(1)=10> IAC SE */
8382 /* wait for response */
8385 debug(F110,"tnc_get_rts_state","begin",0);
8386 if (ttnet != NET_TCPB) return(0);
8387 if (ttnproto != NP_TELNET) return(0);
8389 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8392 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8397 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8398 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8399 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8400 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8401 sb_out[i++] = TNC_CTL_RTS_REQUEST;
8402 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8403 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8406 if (deblog || tn_deb || debses) {
8407 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8408 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8412 NULL,NULL,NULL,NULL,NULL,NULL);
8416 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8419 debug(F100,tn_msg_out,"",0);
8420 if (tn_deb || debses) tn_debug(tn_msg_out);
8422 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8424 ReleaseTelnetMutex();
8429 if (tnc_wait((CHAR *)"comport get rts state",0) < 0) {
8433 debug(F111,"tnc_get_rts_state","end",tnc_rts);
8439 tnc_set_ls_mask(int mask)
8440 #else /* CK_ANSIC */
8441 tnc_set_ls_mask(mask) int mask;
8442 #endif /* CK_ANSIC */
8443 /* tnc_set_ls_mask */ {
8444 /* IAC SB COM_PORT SET_LINESTATE_MASK <value(1)> IAC SE */
8450 * 4 Break Detect Error
8451 * 5 Transfer Holding Register Empty
8452 * 6 Transfer Shift Register Empty
8457 debug(F111,"tnc_set_ls_mask","begin",mask);
8458 if (ttnet != NET_TCPB) return(0);
8459 if (ttnproto != NP_TELNET) return(0);
8461 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8464 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8469 if ( mask != 0 && mask == tnc_ls_mask )
8470 return(tnc_ls_mask);
8472 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8473 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8474 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8475 sb_out[i++] = TNC_C2S_SET_LS_MASK;
8476 sb_out[i++] = (unsigned char)(mask & 0xFF);
8477 if (sb_out[i-1] == IAC )
8479 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8480 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8483 if (deblog || tn_deb || debses) {
8484 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8485 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8486 " SET-LINESTATE-MASK ",
8487 ckitoa(mask & 0xFF),
8489 NULL,NULL,NULL,NULL,NULL,NULL);
8493 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8496 debug(F100,tn_msg_out,"",0);
8497 if (tn_deb || debses) tn_debug(tn_msg_out);
8499 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8501 ReleaseTelnetMutex();
8507 debug(F111,"tnc_set_ls_mask","end",tnc_ls_mask);
8513 tnc_get_ls_mask(void)
8514 #else /* CK_ANSIC */
8516 #endif /* CK_ANSIC */
8517 /* tnc_get_ls_mask */ {
8518 debug(F101,"tnc_get_ls_mask","",tnc_ls_mask);
8519 return(tnc_ls_mask);
8525 #else /* CK_ANSIC */
8527 #endif /* CK_ANSIC */
8530 debug(F101,"tnc_get_ls","",tnc_ls);
8536 tnc_set_ms_mask(int mask)
8537 #else /* CK_ANSIC */
8538 tnc_set_ms_mask(mask) int mask;
8539 #endif /* CK_ANSIC */
8540 /* tnc_set_ms_mask */ {
8541 /* IAC SB COM_PORT SET_MODEMSTATE_MASK <value(1)> IAC SE */
8543 * 0 Delta Clear To Send
8544 * 1 Delta Data Set Ready
8545 * 2 Trailing Edge Ring Detector
8546 * 3 Delta Receive Line Signal (Carrier) Detect
8547 * 4 Clear To Send Signal State
8548 * 5 Data-Set-Ready Signal State
8550 * 7 Receive Line Signal (Carrier) Detect
8555 debug(F111,"tnc_set_ms_mask","begin",mask);
8556 if (ttnet != NET_TCPB) return(0);
8557 if (ttnproto != NP_TELNET) return(0);
8559 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8562 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8567 if ( mask != 0 && mask == tnc_ms_mask )
8568 return(tnc_ms_mask);
8570 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8571 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8572 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8573 sb_out[i++] = TNC_C2S_SET_MS_MASK;
8574 sb_out[i++] = (unsigned char)(mask & 0xFF);
8575 if (sb_out[i-1] == IAC )
8577 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8578 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8581 if (deblog || tn_deb || debses) {
8582 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8583 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8584 " SET-MODEMSTATE-MASK ",
8585 ckitoa(mask & 0xFF),
8587 NULL,NULL,NULL,NULL,NULL,NULL);
8591 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8594 debug(F100,tn_msg_out,"",0);
8595 if (tn_deb || debses) tn_debug(tn_msg_out);
8597 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8599 ReleaseTelnetMutex();
8605 debug(F111,"tnc_set_ms_mask","end",tnc_ms_mask);
8611 tnc_get_ms_mask(void)
8612 #else /* CK_ANSIC */
8614 #endif /* CK_ANSIC */
8615 /* tnc_get_ms_mask */ {
8616 debug(F101,"tnc_get_gs_mask","",tnc_ms_mask);
8617 return(tnc_ms_mask);
8623 #else /* CK_ANSIC */
8625 #endif /* CK_ANSIC */
8628 debug(F101,"tnc_get_ms","",tnc_ms);
8634 tnc_send_purge_data(int mode)
8635 #else /* CK_ANSIC */
8636 tnc_send_purge_data(mode) int mode;
8637 #endif /* CK_ANSIC */
8638 /* tnc_send_purge_data */ {
8639 /* IAC SB COM_PORT PURGE_DATA <value(1)> IAC SE */
8641 * 1 Purge access server receive data buffer
8642 * 2 Purge access server transmit data buffer
8643 * 3 Purge access server receive and transmit data buffers
8648 debug(F111,"tnc_send_purge_data","begin",mode);
8649 if (ttnet != NET_TCPB) return(0);
8650 if (ttnproto != NP_TELNET) return(0);
8652 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8655 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8660 if ( !(mode >= 1 && mode <= 3) )
8663 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8664 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8665 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8666 sb_out[i++] = TNC_C2S_PURGE;
8667 sb_out[i++] = (unsigned char)(mode & 0xFF);
8668 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8669 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8672 if (deblog || tn_deb || debses) {
8673 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8674 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8676 ckitoa(mode & 0xFF),
8678 NULL,NULL,NULL,NULL,NULL,NULL);
8682 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8685 debug(F100,tn_msg_out,"",0);
8686 if (tn_deb || debses) tn_debug(tn_msg_out);
8688 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8690 ReleaseTelnetMutex();
8694 debug(F110,"tnc_send_purge_data","end",0);
8700 tnc_flow_suspended(void)
8701 #else /* CK_ANSIC */
8702 tnc_flow_suspended()
8703 #endif /* CK_ANSIC */
8704 /* tnc_flow_suspended */ {
8705 debug(F111,"tnc_flow_suspended","",tnc_suspend_xmit);
8706 return(tnc_suspend_xmit);
8711 tnc_suspend_flow(void)
8712 #else /* CK_ANSIC */
8714 #endif /* CK_ANSIC */
8715 /* tnc_suspend_flow */ {
8716 /* IAC SB COM_PORT FLOWCONTROL_SUSPEND IAC SE */
8719 debug(F110,"tnc_suspend_flow","begin",0);
8720 if (ttnet != NET_TCPB) return(0);
8721 if (ttnproto != NP_TELNET) return(0);
8723 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8726 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8731 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8732 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8733 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8734 sb_out[i++] = TNC_C2S_FLOW_SUSPEND;
8735 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8736 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8739 if (deblog || tn_deb || debses) {
8740 ckmakmsg(tn_msg_out,TN_MSG_LEN,
8741 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8742 " FLOWCONTROL-SUSPEND IAC SE", NULL);
8746 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8749 debug(F100,tn_msg_out,"",0);
8750 if (tn_deb || debses) tn_debug(tn_msg_out);
8752 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8754 ReleaseTelnetMutex();
8758 debug(F110,"tnc_suspend_flow","end",0);
8764 tnc_resume_flow(void)
8765 #else /* CK_ANSIC */
8767 #endif /* CK_ANSIC */
8768 /* tnc_resume_flow */ {
8769 /* IAC SB COM_PORT FLOWCONTROL_RESUME IAC SE */
8772 debug(F110,"tnc_resume_flow","begin",0);
8773 if (ttnet != NET_TCPB) return(0);
8774 if (ttnproto != NP_TELNET) return(0);
8776 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8779 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8784 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8785 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8786 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8787 sb_out[i++] = TNC_C2S_FLOW_RESUME;
8788 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8789 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8792 if (deblog || tn_deb || debses) {
8793 ckmakmsg(tn_msg_out,TN_MSG_LEN,
8794 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8795 " FLOWCONTROL-RESUME IAC SE", NULL);
8799 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8802 debug(F100,tn_msg_out,"",0);
8803 if (tn_deb || debses) tn_debug(tn_msg_out);
8805 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8807 ReleaseTelnetMutex();
8811 debug(F110,"tnc_resume_flow","end",0);
8817 tnsetflow(int nflow)
8819 tnsetflow(nflow) int nflow;
8820 #endif /* CK_ANSIC */
8825 debug(F111,"tnsetflow","begin",nflow);
8826 if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
8829 if (TELOPT_ME(TELOPT_COMPORT)) {
8833 TNC_CTL_OFLOW_XON_XOFF
8837 TNC_CTL_IFLOW_XON_XOFF
8842 TNC_CTL_OFLOW_RTS_CTS
8846 TNC_CTL_IFLOW_RTS_CTS
8850 /* leave things exactly as they are */
8854 case FLO_DIAL: /* dialing hack */
8855 case FLO_DIAX: /* cancel dialing hack */
8874 debug(F111,"tnsetflow","end",rc);
8875 return(rc >= 0 ? 0 : -1);
8880 tnsettings(int par, int stop)
8882 tnsettings(par, stop) int par, stop;
8883 #endif /* CK_ANSIC */
8887 extern int hwparity;
8889 debug(F111,"tnsettings begin","par",par);
8890 debug(F111,"tnsettings begin","stop",stop);
8891 if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
8894 datasize = par ? TNC_DS_7 : TNC_DS_8;
8895 if (!par) par = hwparity;
8897 if (TELOPT_ME(TELOPT_COMPORT)) {
8900 rc = tnc_set_parity(TNC_PAR_EVEN);
8902 rc = tnc_set_datasize(datasize);
8905 rc = tnc_set_parity(TNC_PAR_ODD);
8907 rc = tnc_set_datasize(datasize);
8910 rc = tnc_set_parity(TNC_PAR_MARK);
8912 rc = tnc_set_datasize(datasize);
8915 rc = tnc_set_parity(TNC_PAR_SPACE);
8917 rc = tnc_set_datasize(datasize);
8921 rc = tnc_set_parity(TNC_PAR_NONE);
8923 rc = tnc_set_datasize(datasize);
8932 rc = tnc_set_stopsize(TNC_SB_2);
8936 rc = tnc_set_stopsize(TNC_SB_1);
8944 debug(F111,"tnsettings","end",rc);
8945 return((rc >= 0) ? 0 : -1);
8948 /* T N G M D M -- Telnet Get modem signals */
8950 Looks for the modem signals CTS, DSR, and CTS, and returns those that are
8951 on in as its return value, in a bit mask as described for ttwmdm.
8954 -2 if the line does not have modem control
8956 >= 0 on success, with a bit mask containing the modem signals that are on.
8963 #endif /* CK_ANSIC */
8968 debug(F110,"tngmdm","begin",0);
8969 if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
8972 if (TELOPT_ME(TELOPT_COMPORT)) {
8973 int modemstate = tnc_get_ms();
8975 if (modemstate & TNC_MS_CTS_SIG)
8977 if (modemstate & TNC_MS_DSR_SIG)
8979 if (modemstate & TNC_MS_RI_SIG)
8981 if (modemstate & TNC_MS_RLSD_SIG)
8983 debug(F111,"tngmdm","end",modem);
8986 debug(F111,"tngmdm","end",-2);
8995 tnsndb(wait) long wait;
8996 #endif /* CK_ANSIC */
9000 debug(F111,"tnsndb","begin",wait);
9001 if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
9004 if (TELOPT_ME(TELOPT_COMPORT)) {
9005 rc = tnc_set_break_state(1);
9007 msleep(wait); /* ZZZzzz */
9008 rc = tnc_set_break_state(0);
9011 debug(F111,"tnsndb","end",rc);
9012 return((rc >= 0) ? 0 : -1);
9014 #endif /* TN_COMPORT */