1 char *cktelv = "Telnet support, 8.0.269, 4 Mar 2004";
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, 2004,
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 */
94 extern int inserver; /* Running as IKSD */
95 char *tn_term = NULL; /* Terminal type override */
98 char *tn_loc = NULL; /* Location override */
99 #endif /* CK_SNDLOC */
100 int tn_nlm = TNL_CRLF; /* Telnet CR -> CR LF mode */
101 int tn_b_nlm = TNL_CR; /* Telnet Binary CR RAW mode */
102 int tn_b_meu = 0; /* Telnet Binary ME means U too */
103 int tn_b_ume = 0; /* Telnet Binary U means ME too */
104 int tn_wait_flg = 1; /* Telnet Wait for Negotiations */
105 int tn_infinite = 0; /* Telnet Bug Infinite-Loop-Check */
106 int tn_rem_echo = 1; /* We will echo if WILL ECHO */
107 int tn_b_xfer = 0; /* Telnet Binary for Xfers? */
108 int tn_sb_bug = 1; /* Telnet BUG - SB w/o WILL or DO */
109 int tn_auth_krb5_des_bug = 1; /* Telnet BUG - AUTH KRB5 DES */
110 /* truncates long keys */
111 int tn_no_encrypt_xfer = 0; /* Turn off Telnet Encrypt? */
112 int tn_delay_sb = 1; /* Delay SBs until safe */
113 int tn_auth_how = TN_AUTH_HOW_ANY;
114 int tn_auth_enc = TN_AUTH_ENC_ANY;
115 int tn_deb = 0; /* Telnet Debug mode */
116 int tn_sfu = 0; /* Microsoft SFU compatibility */
118 char * tn_fwdx_xauthority = NULL; /* Xauthority File */
119 int fwdx_no_encrypt = 0; /* Forward-X requires encryption */
120 #endif /* CK_FORWARD_X */
123 int ttnum = -1; /* Last Telnet Terminal Type sent */
124 int ttnumend = 0; /* Has end of list been found */
127 char tn_msg[TN_MSG_LEN]; /* Telnet data can be rather long */
128 char hexbuf[TN_MSG_LEN];
129 char tn_msg_out[TN_MSG_LEN];
131 CHAR fwdx_msg_out[TN_MSG_LEN];
132 #endif /* CK_FORWARD_X */
135 In order to prevent an infinite telnet negotiation loop we maintain a
136 count of the number of times the same telnet negotiation message is
137 sent. When this count hits MAXTNCNT, we do not send any more of the
138 message. The count is stored in the tncnts[][] array.
140 The tncnts[][] array is indexed by negotiation option (SUPPRESS GO AHEAD,
141 TERMINAL TYPE, NAWS, etc. - see the tnopts[] array) and the four
142 negotiation message types (WILL, WONT, DO, DONT). All telnet negotiations
143 are kept track of in this way.
145 The count for a message is zeroed when the "opposite" message is sent.
146 WILL is the opposite of WONT, and DO is the opposite of DONT.
147 For example sending "WILL SGA" increments tncnts[TELOPT_SGA][0]
148 and zeroes tncnts[TELOPT_SGA][1].
150 The code that does this is in tn_sopt().
152 rogersh@fsj.co.jp, 18/3/1995
154 8/16/1998 - with the recent rewrite of the telnet state machine I don't
155 think this code is necessary anymore. However, it can't do any harm so
156 I am leaving it in. - Jeff
158 12/28/1998 - all references to tncnts[] must be done with TELOPT_INDEX(opt)
159 because the Telnet option list is no longer contiguous. We also must
160 allocate NTELOPTS + 1 because the TELOPT_INDEX() macro returns NTELOPTS
161 for an invalid option number.
164 #define MAXTNCNT 4 /* Permits 4 intermediate telnet firewalls/gateways */
166 char tncnts[NTELOPTS+1][4]; /* Counts */
167 char tnopps[4] = { 1,0,3,2 }; /* Opposites */
169 #ifdef CK_ENVIRONMENT
171 #define TSBUFSIZ 2056
172 #else /* CK_FORWARD_X */
173 #define TSBUFSIZ 1024
174 #endif /* CK_FORWARD_X */
175 char tn_env_acct[64];
176 char tn_env_disp[64];
178 char tn_env_prnt[64];
180 char * tn_env_uservar[8][2];
182 #else /* CK_ENVIRONMENT */
185 #endif /* CK_ENVIRONMENT */
188 /* SIGWINCH handler moved to ckuusx.c */
190 #ifdef CK_NAWS /* Window size business */
195 #endif /* NOSIGWINCH */
198 CHAR sb[TSBUFSIZ]; /* Buffer - incoming subnegotiations */
199 CHAR sb_out[TSBUFSIZ]; /* Buffer - outgoing subnegotiations */
201 int tn_duplex = 1; /* Local echo */
203 extern char uidbuf[]; /* User ID buffer */
204 extern int quiet, ttnet, ttnproto, debses, what, duplex, oldplex, local;
205 extern int seslog, sessft, whyclosed;
208 extern int tt_rows[], tt_cols[];
209 extern int tt_status[VNUM];
210 extern int scrninitialized[];
213 extern int tt_rows, tt_cols; /* Everybody has this */
215 extern int cmd_cols, cmd_rows;
216 extern char namecopy[];
217 extern char myipaddr[]; /* Global copy of my IP address */
221 telopt_index(opt) int opt; {
222 if (opt >= 0 && opt <= TELOPT_STDERR)
224 else if (opt >= TELOPT_PRAGMA_LOGON && opt <= TELOPT_PRAGMA_HEARTBEAT)
226 else if (opt == TELOPT_IBM_SAK)
233 telopt_ok(opt) int opt; {
234 return((opt >= TELOPT_BINARY && opt <= TELOPT_STDERR) ||
235 (opt >= TELOPT_PRAGMA_LOGON && opt <= TELOPT_PRAGMA_HEARTBEAT) ||
236 (opt == TELOPT_IBM_SAK));
240 telopt(opt) int opt; {
242 return((CHAR *)telopts[telopt_index(opt)]);
244 return((CHAR *)"UNKNOWN");
248 telopt_mode_ok(opt) int opt; {
249 return((unsigned int)(opt) <= TN_NG_MU);
253 telopt_mode(opt) int opt; {
254 if (telopt_mode_ok(opt))
255 return((CHAR *)telopt_modes[opt-TN_NG_RF]);
257 return((CHAR *)"UNKNOWN");
259 #endif /* TELOPT_MACRO */
262 tn_outst(notquiet) int notquiet; {
268 #endif /* CK_ENCRYPTION */
271 for (x = TELOPT_FIRST; x <= TELOPT_LAST; x++) {
273 if (TELOPT_UNANSWERED_WILL(x)) {
275 printf("?Telnet waiting for response to WILL %s\r\n",
277 debug(F111,"tn_outst","unanswered WILL",x);
282 if (TELOPT_UNANSWERED_DO(x)) {
284 printf("?Telnet waiting for response to DO %s\r\n",
286 debug(F111,"tn_outst","unanswered DO",x);
291 if (TELOPT_UNANSWERED_WONT(x)) {
293 printf("?Telnet waiting for response to WONT %s\r\n",
295 debug(F111,"tn_outst","unanswered WONT",x);
300 if (TELOPT_UNANSWERED_DONT(x)) {
302 printf("?Telnet waiting for response to DONT %s\r\n",
304 debug(F111,"tn_outst","unanswered DONT",x);
309 if (TELOPT_UNANSWERED_SB(x)) {
311 printf("?Telnet waiting for response to SB %s\r\n",
313 debug(F111,"tn_outst","unanswered SB",x);
320 #ifdef CK_AUTHENTICATION
321 if (ck_tn_auth_in_progress()) {
322 if (TELOPT_ME(TELOPT_AUTHENTICATION)) {
324 printf("?Telnet waiting for WILL %s subnegotiation\r\n",
325 TELOPT(TELOPT_AUTHENTICATION));
328 "ME authentication in progress",
329 TELOPT_AUTHENTICATION
332 } else if (TELOPT_U(TELOPT_AUTHENTICATION)) {
334 printf("?Telnet waiting for DO %s subnegotiation\r\n",
335 TELOPT(TELOPT_AUTHENTICATION));
338 "U authentication in progress",
339 TELOPT_AUTHENTICATION
344 #endif /* CK_AUTHENTICATION */
347 e = ck_tn_encrypting();
348 d = ck_tn_decrypting();
349 if (TELOPT_ME(TELOPT_ENCRYPTION)) {
350 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && e ||
351 !TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && !e
354 printf("?Telnet waiting for WILL %s subnegotiation\r\n",
355 TELOPT(TELOPT_ENCRYPTION));
358 "encryption mode switch",
364 if (TELOPT_U(TELOPT_ENCRYPTION)) {
365 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && d ||
366 !TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && !d
369 printf("?Telnet waiting for DO %s subnegotiation\r\n",
370 TELOPT(TELOPT_ENCRYPTION));
373 "decryption mode switch",
380 #endif /* CK_ENCRYPTION */
381 } /* if (tn_wait_flg) */
384 /* Even if we are not waiting for Telnet options we must wait for */
385 /* Kermit Telnet Subnegotiations if we have sent a request to the */
386 /* other guy. Otherwise we will get out of sync. */
388 if (TELOPT_U(TELOPT_KERMIT) &&
389 (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start ||
390 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop ||
391 !TELOPT_SB(TELOPT_KERMIT).kermit.sop)
394 printf("?Telnet waiting for SB %s negotiation\r\n",
395 TELOPT(TELOPT_KERMIT));
396 debug(F111,"tn_outst","U kermit in progress",TELOPT_KERMIT);
400 #endif /* IKS_OPTION */
404 if (TELOPT_ME(TELOPT_COMPORT)) {
405 if (TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb) {
407 printf("?Telnet waiting for SB %s negotiation\r\n",
408 TELOPT(TELOPT_COMPORT));
409 debug(F111,"tn_outst","ComPort SB in progress",TELOPT_COMPORT);
412 if (TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms) {
414 printf("?Telnet waiting for SB %s MODEM_STATUS negotiation\r\n",
415 TELOPT(TELOPT_COMPORT));
416 debug(F111,"tn_outst","ComPort SB MS in progress",TELOPT_COMPORT);
421 #endif /* TN_COMPORT */
428 if (!local) return(0);
429 if (ttnet != NET_TCPB) return(0);
430 if (ttnproto != NP_TELNET) return(0);
431 if (TELOPT_ME(TELOPT_COMPORT))
434 #endif /* TN_COMPORT */
438 /* tn_wait() -- Wait for response to Telnet negotiation. */
440 Wait for up to <timeout> seconds for the response to arrive.
441 Place all non-telnet data into Telnet Wait Buffer.
442 If response does arrive return 1, else return 0.
444 #ifndef TN_WAIT_BUF_SZ
445 #define TN_WAIT_BUF_SZ 4096
446 #endif /* TN_WAIT_BUF_SZ */
447 static char tn_wait_buf[TN_WAIT_BUF_SZ];
448 static int tn_wait_idx = 0;
450 #define TN_TIMEOUT 120
451 #endif /* TN_TIMEOUT */
452 static int tn_wait_tmo = TN_TIMEOUT;
456 prtwait(state) int state; {
472 #endif /* CKSPINNER */
474 static int nflag = 0;
478 tn_wait(char * where)
480 tn_wait(where) char * where;
481 #endif /* CK_ANSIC */
483 extern int ckxech, local;
484 int ch = 0, count = 0;
493 #endif /* TN_COMPORT */
497 debug(F110,"tn_wait waiting for",where,0);
498 tn_wait_tmo = TN_TIMEOUT;
499 debug(F111,"tn_wait","timeout",tn_wait_tmo);
500 outstanding = tn_outst(0);
501 debug(F111,"tn_wait","outstanding",outstanding);
502 debug(F111,"tn_wait","tn_wait_flg",tn_wait_flg);
504 /* The following is meant to be !(||). We only want to return */
505 /* immediately if both the tn_wait_flg && tn_outst() are false */
506 if (!(outstanding || tn_wait_flg)) /* If no need to wait */
507 return(1); /* Don't. */
509 if (tn_deb || debses) tn_debug("<wait for outstanding negotiations>");
512 if (!sstelnet && !quiet)
514 #endif /* CKSPINNER */
516 /* Wait up to TN_TIMEOUT sec for responses to outstanding telnet negs */
522 if (ch == -1) { /* Timed out */
523 if (!sstelnet && !quiet) { /* Let user know... */
529 printf(" Negotiations.");
537 #endif /* CKSPINNER */
539 } else if (ch < -1) {
540 printf("\r\n?Connection closed by peer.\r\n");
541 if (tn_deb || debses) tn_debug("<connection closed by peer>");
547 if (!sstelnet && !quiet)
549 #endif /* CKSPINNER */
550 ch = tn_doop((CHAR)(ch & 0xff),inserver?ckxech:duplex,ttinc);
552 if (!sstelnet && !quiet) {
555 #endif /* CKSPINNER */
556 debug(F101,"tn_wait tn_doop","",ch);
559 duplex = 1; /* Turn on echoing */
564 duplex = 0; /* Turn off echoing */
569 tn_wait_buf[tn_wait_idx++] = IAC;
571 case 4: /* IKS event */
576 printf("?Telnet Option negotiation error.\n");
577 if (tn_deb || debses)
578 tn_debug("<Telnet Option negotiation error>");
581 printf("?Connection closed by peer.\n");
582 if (tn_deb || debses) tn_debug("<Connection closed by peer>");
587 if (tn_deb || debses) tn_debug("<Unknown connection error>");
594 if (!sstelnet && !quiet) {
598 #endif /* CKSPINNER */
599 tn_wait_buf[tn_wait_idx++] = (CHAR)(ch & 0xff);
602 outstanding = tn_outst(0);
604 if ( outstanding && ch != IAC ) {
605 int timer = gtimer();
606 if ( timer > tn_wait_tmo ) {
609 "\r\n?Telnet Protocol Timeout - connection closed\r\n");
610 if (tn_deb || debses)
612 "<telnet protocol timeout - connection closed>");
615 /* if we do not close the connection, then we will block */
616 /* the next time we hit a wait. and if we don't we will */
617 /* do the wrong thing if the host sends 0xFF and does */
618 /* not intend it to be an IAC. */
620 whyclosed = WC_TELOPT;
624 else if ( hints && timer > 30 && nohintgiven && !inserver ) {
627 #else /* CKSPINNER */
629 #endif /* CKSPINNER */
630 printf("*************************\r\n");
631 printf("The Telnet %s is not sending required responses.\r\n\r\n",
632 sstelnet?"client":"server");
634 printf("\nYou can continue to wait or you can cancel with Ctrl-C.\r\n");
635 printf("In case the Telnet server never responds as required,\r\n");
636 printf("you can try connecting to this host with TELNET /NOWAIT.\r\n");
637 printf("Use SET HINTS OFF to suppress further hints.\r\n");
638 printf("*************************\r\n");
645 /* Must disable carrier detect check if we are using Telnet Comport */
650 #else /* TN_COMPORT */
652 #endif /* TN_COMPORT */
653 } while ((tn_wait_idx < TN_WAIT_BUF_SZ) &&
654 (outstanding && count >= 0));
656 if (tn_wait_idx == TN_WAIT_BUF_SZ) {
657 if (tn_deb || debses) tn_debug("<Telnet Wait Buffer filled>");
661 if (!sstelnet && !quiet) {
669 #endif /* CKSPINNER */
671 if (tn_deb || debses) tn_debug("<no outstanding negotiations>");
675 /* Push data from the Telnet Wait Buffer into the I/O Queue */
676 /* Return 1 on success */
681 extern int tt_push_inited;
682 #endif /* NETLEBUF */
684 hexdump((CHAR *)"tn_push",tn_wait_buf,tn_wait_idx);
686 if (!tt_push_inited) /* Local handling */
688 le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
689 #else /* External handling... */
690 #ifdef OS2 /* K95 has its own way */
691 le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
693 #ifdef TTLEBUF /* UNIX, etc */
694 le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
697 If you see this message in AOS/VS, OS-9, VOS, etc, you need to copy
698 the #ifdef TTLEBUF..#endif code from ckutio.c to the corresponding
699 places in your ck?tio.c module.
701 printf("tn_push called but not implemented - data lost.\n");
704 #endif /* NETLEBUF */
707 tn_wait_tmo = TN_TIMEOUT; /* Reset wait timer stats */
713 Sends a telnet option, avoids loops.
714 Returns 1 if command was sent, 0 if not, -1 on error.
717 tn_sopt(cmd,opt) int cmd, opt; { /* TELNET SEND OPTION */
722 if (ttnet != NET_TCPB) return(-1); /* Must be TCP/IP */
723 if (ttnproto != NP_TELNET) return(-1); /* Must be telnet protocol */
724 if (!TELCMD_OK(cmd)) return(-1);
725 if (TELOPT_OK(opt)) {
726 if (cmd == DO && TELOPT_UNANSWERED_DO(opt)) return(0);
727 if (cmd == WILL && TELOPT_UNANSWERED_WILL(opt)) return(0);
728 if (cmd == DONT && TELOPT_UNANSWERED_DONT(opt)) return(0);
729 if (cmd == WONT && TELOPT_UNANSWERED_WONT(opt)) return(0);
732 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
737 if (cmd == DO && opt == TELOPT_AUTHENTICATION)
740 if (tn_infinite && TELOPT_OK(opt)) { /* See comment above about */
741 int index = TELOPT_INDEX(opt); /* preventing infinite loops */
744 if (tncnts[index][m] > MAXTNCNT) {
746 if (tn_deb || debses || deblog) {
747 ckmakmsg(msg,sizeof(msg),
748 "TELNET negotiation loop ",
751 debug(F101,msg,"",opt);
752 if (tn_deb || debses) tn_debug(msg);
758 tncnts[index][tnopps[m]] = 0;
761 buf[1] = (CHAR) (cmd & 0xff);
762 buf[2] = (CHAR) (opt & 0xff);
765 if ((tn_deb || debses || deblog) && cmd != SB)
766 ckmakmsg(msg,sizeof(msg),"TELNET SENT ",TELCMD(cmd)," ",
770 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
772 debug(F101,msg,"",opt);
773 if ((tn_deb || debses) && cmd != SB)
775 rc = (ttol(buf,3) < 3);
777 ReleaseTelnetMutex();
783 if (TELOPT_OK(opt)) {
784 if (cmd == DONT && TELOPT_UNANSWERED_DO(opt))
785 TELOPT_UNANSWERED_DO(opt) = 0;
786 if (cmd == WONT && TELOPT_UNANSWERED_WILL(opt))
787 TELOPT_UNANSWERED_WILL(opt) = 0;
788 if (cmd == DO && TELOPT_UNANSWERED_DONT(opt))
789 TELOPT_UNANSWERED_DONT(opt) = 0;
790 if (cmd == WILL && TELOPT_UNANSWERED_WONT(opt))
791 TELOPT_UNANSWERED_WONT(opt) = 0;
796 /* Send a telnet sub-option */
797 /* Returns 1 if command was sent, 0 if not, -1 on error */
800 tn_ssbopt(opt,sub,data,len) int opt, sub; CHAR * data; int len; {
804 if (ttnet != NET_TCPB) return(0); /* Must be TCP/IP */
805 if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
806 if (!TELOPT_OK(opt)) return(-1);
807 if (len < 0 || len > 250) {
808 debug(F111,"Unable to Send TELNET SB - data too long","len",len);
809 return(-1); /* Data too long */
812 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
823 buf[1] = (CHAR) (SB & 0xff);
824 buf[2] = (CHAR) (opt & 0xff);
825 buf[3] = (CHAR) (sub & 0xff);
826 if (data && len > 0) {
827 memcpy(&buf[4],data,len);
829 buf[4+len] = (CHAR) IAC;
830 buf[5+len] = (CHAR) SE;
833 if (tn_deb || debses || deblog) {
834 if (opt == TELOPT_START_TLS && sub == 1)
835 ckmakmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
836 TELOPT(opt)," FOLLOWS IAC SE",NULL);
837 else if (opt == TELOPT_TTYPE && sub == 1)
838 ckmakmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ", TELOPT(opt),
839 " SEND IAC SE",NULL);
840 else if (opt == TELOPT_TTYPE && sub == 0)
841 ckmakxmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",TELOPT(opt)," IS ",
842 (char *)data," IAC SE",NULL,NULL,NULL,NULL,NULL,NULL,NULL);
843 else if (opt == TELOPT_NEWENVIRON) {
845 ckmakmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
846 TELOPT(TELOPT_NEWENVIRON)," ",
847 sub == TELQUAL_SEND ? "SEND" :
848 sub == TELQUAL_IS ? "IS" :
849 sub == TELQUAL_INFO ?"INFO" : "UNKNOWN" );
850 for (i = 0, quote = 0; i < len; i++) {
852 sprintf(hexbuf,"%02x",data[i]); /* safe but ugly */
853 ckstrncat(tn_msg_out,hexbuf,TN_MSG_LEN);
857 case TEL_ENV_USERVAR:
858 ckstrncat(tn_msg_out," USERVAR ",TN_MSG_LEN);
861 ckstrncat(tn_msg_out," VAR ",TN_MSG_LEN);
864 ckstrncat(tn_msg_out," VALUE ",TN_MSG_LEN);
867 ckstrncat(tn_msg_out," ESC ",TN_MSG_LEN);
871 ckstrncat(tn_msg_out," IAC ",TN_MSG_LEN);
874 sprintf(hexbuf,"%c",data[i]); /* safe but ugly */
875 ckstrncat(tn_msg_out,hexbuf,TN_MSG_LEN);
879 ckstrncat(tn_msg_out," IAC SE",TN_MSG_LEN);
881 sprintf(hexbuf,"%02x",sub); /* safe but ugly */
882 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
883 "TELNET SENT SB ",TELOPT(opt),
887 NULL,NULL,NULL,NULL,NULL,NULL,NULL
893 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
896 debug(F101,tn_msg_out,"",opt);
897 if (tn_deb || debses)
898 tn_debug(tn_msg_out);
900 rc = (ttol(buf,6+len) < 6+len);
902 ReleaseTelnetMutex();
911 tn_flui() -- Processes all waiting data for Telnet commands.
912 All non-Telnet data is to be stored into the Telnet Wait Buffer.
913 Returns 1 on success.
920 /* Wait up to 5 sec for responses to outstanding telnet negotiations */
921 while (x >= 0 && ttchk() > 0 && tn_wait_idx < TN_WAIT_BUF_SZ) {
925 x = tn_doop((CHAR)(x & 0xff),inserver?ckxech:duplex,ttinc);
926 debug(F101,"tn_flui tn_doop","",x);
928 case 1: /* Turn on echoing */
933 case 2: /* Turn off echoing */
939 tn_wait_buf[tn_wait_idx++] = IAC;
941 case 4: /* IKS event */
948 tn_wait_buf[tn_wait_idx++] = x;
958 static char tmploc[256];
960 /* Must compute the DISPLAY string we are going to send to the host */
961 /* If one is not assigned, do not send a string unless the user has */
962 /* explicitedly requested we try to send one via X-Display Location */
963 /* But do not send a string at all if FORWARD_X is in use. */
965 debug(F110,"tn_get_display() myipaddr",myipaddr,0);
966 #ifdef CK_ENVIRONMENT
967 debug(F110,"tn_get_display() tn_env_disp",tn_env_disp,0);
968 if (tn_env_disp[0]) {
969 int colon = ckindex(":",tn_env_disp,0,0,1);
971 ckmakmsg(tmploc,256,myipaddr,":",tn_env_disp,NULL);
973 } else if ( ckindex("localhost:",tn_env_disp,0,0,0) ||
974 ckindex("unix:",tn_env_disp,0,0,0) ||
975 ckindex("127.0.0.1:",tn_env_disp,0,0,0) ||
976 !ckstrcmp("0:",tn_env_disp,2,1) ||
977 tn_env_disp[0] == ':' ) {
978 ckmakmsg(tmploc,256,myipaddr,":",&tn_env_disp[colon],NULL);
984 #endif /* CK_ENVIRONMENT */
985 if (TELOPT_ME(TELOPT_XDISPLOC) ||
986 TELOPT_U(TELOPT_FORWARD_X)) {
987 ckmakmsg(tmploc,256,myipaddr,":0.0",NULL,NULL);
990 debug(F110,"tn_get_display() returns",disp,0);
991 return((CHAR *)disp);
995 static Xauth fake_xauth = {0,0,NULL,0,NULL,0,NULL,0,NULL};
996 static Xauth *real_xauth=NULL;
999 * Author: Jim Fulton, MIT X Consortium
1001 * fwdx_parse_displayname -
1002 * display a display string up into its component parts
1005 #define UNIX_CONNECTION "unix"
1006 #define UNIX_CONNECTION_LENGTH 4
1010 * private utility routines
1015 XmuGetHostname (char *buf, int maxlen)
1017 XmuGetHostname (buf, maxlen)
1020 #endif /* CK_ANSIC */
1026 * same host name crock as in server and xinit.
1028 struct utsname name;
1031 len = strlen (name.nodename);
1032 if (len >= maxlen) len = maxlen - 1;
1033 strncpy (buf, name.nodename, len);
1037 (void) gethostname (buf, maxlen);
1038 buf [maxlen - 1] = '\0';
1046 copystring (char *src, int len)
1048 copystring (src, len)
1051 #endif /* CK_ANSIC */
1055 if (!src && len != 0) return NULL;
1056 cp = malloc (len + 1);
1058 if (src) strncpy (cp, src, len);
1066 get_local_hostname (char *buf, int maxlen)
1068 get_local_hostname (buf, maxlen)
1074 (void) XmuGetHostname (buf, maxlen);
1075 return (buf[0] ? buf : NULL);
1084 return (get_local_hostname (buf, sizeof buf) ?
1085 copystring (buf, strlen (buf)) : NULL);
1092 fwdx_parse_displayname (char *displayname, int *familyp, char **hostp,
1093 int *dpynump, int *scrnump, char **restp)
1095 fwdx_parse_displayname (displayname, familyp, hostp, dpynump, scrnump, restp)
1097 int *familyp; /* return */
1098 char **hostp; /* return */
1099 int *dpynump, *scrnump; /* return */
1100 char **restp; /* return */
1101 #endif /* CK_ANSIC */
1103 char *ptr; /* work variables */
1104 int len; /* work variable */
1105 int family = -1; /* value to be returned */
1106 char *host = NULL; /* must free if set and error return */
1107 int dpynum = -1; /* value to be returned */
1108 int scrnum = 0; /* value to be returned */
1109 char *rest = NULL; /* must free if set and error return */
1110 int dnet = 0; /* if 1 then using DECnet */
1112 /* check the name */
1113 if (!displayname || !displayname[0])
1115 /* must have at least :number */
1116 ptr = (char *)strchr(displayname, ':');
1117 if (!ptr || !ptr[1]) return 0;
1118 if (ptr[1] == ':') {
1119 if (ptr[2] == '\0') return 0;
1124 * get the host string; if none is given, use the most effiecient path
1127 len = (ptr - displayname); /* length of host name */
1128 if (len == 0) { /* choose most efficient path */
1130 host = copystring (UNIX_CONNECTION, UNIX_CONNECTION_LENGTH);
1131 family = FamilyLocal;
1134 host = copystring ("0", 1);
1135 family = FamilyDECnet;
1137 host = copyhostname ();
1138 family = FamilyInternet;
1142 host = copystring (displayname, len);
1147 if (host && strcmp (host, UNIX_CONNECTION) == 0)
1148 family = FamilyLocal;
1151 family = FamilyInternet;
1155 if (!host) return 0;
1159 * get the display number; we know that there is something after the
1160 * colon (or colons) from above. note that host is now set and must
1161 * be freed if there is an error.
1164 if (dnet) ptr++; /* skip the extra DECnet colon */
1165 ptr++; /* move to start of display num */
1169 for (cp = ptr; *cp && isascii(*cp) && isdigit(*cp); cp++) ;
1171 /* check present and valid follow */
1172 if (len == 0 || (*cp && *cp != '.')) {
1177 dpynum = atoi (ptr); /* it will handle num. as well */
1182 * now get screen number if given; ptr may point to nul at this point
1184 if (ptr[0] == '.') {
1188 for (cp = ptr; *cp && isascii(*cp) && isdigit(*cp); cp++) ;
1190 if (len == 0 || (*cp && *cp != '.')) { /* all prop name */
1195 scrnum = atoi (ptr); /* it will handle num. as well */
1200 * and finally, get any additional stuff that might be following the
1201 * the screen number; ptr must point to a period if there is anything
1204 if (ptr[0] == '.') {
1208 rest = copystring (ptr, len);
1240 fwdx_tn_sb( unsigned char * sb, int n )
1242 fwdx_tn_sb( sb, n ) unsigned char * sb; int n;
1243 #endif /* CK_ANSIC */
1245 unsigned short hchannel, nchannel;
1250 /* check to ensure we have negotiated Forward X */
1251 if ( sstelnet && !TELOPT_ME(TELOPT_FORWARD_X) ||
1252 !sstelnet && !TELOPT_U(TELOPT_FORWARD_X) ) {
1253 debug(F100,"fwdx_tn_sb() not negotiated","",0);
1258 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1265 if (sstelnet && n == 4)
1266 rc = fwdx_create_listen_socket(sb[1]);
1269 if ( !sstelnet && n >= 5 ) {
1270 p = (unsigned char *) &nchannel;
1272 /* IAC quoting has been stripped in tn_sb() */
1275 hchannel = ntohs(nchannel);
1276 rc = fwdx_open_client_channel(hchannel);
1278 /* Failed; Send CLOSE channel */
1279 fwdx_send_close(hchannel);
1280 rc = 0; /* Do not consider this to be a telnet error */
1283 if ( !TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started ) {
1284 ckThreadBegin( &fwdx_thread,32655, 0, FALSE, 0 ) ;
1285 TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 1;
1291 p = (unsigned char *) &nchannel;
1293 /* IAC quoting has been stripped in tn_sb() */
1296 hchannel = ntohs(nchannel);
1297 fwdx_close_channel(hchannel);
1298 rc = 0; /* no errors when closing */
1301 p = (unsigned char *) &nchannel;
1303 /* IAC quoting has been stripped in tn_sb() */
1306 hchannel = ntohs(nchannel);
1307 rc = fwdx_send_xauth_to_xserver(hchannel,(char *)&sb[3],n-5);
1308 if ( rc >= 0 && n-5-rc > 0) {
1309 rc = fwdx_write_data_to_channel(hchannel,(char *)&sb[3+rc],n-5-rc);
1311 /* Failed; Send CLOSE channel */
1312 rc = fwdx_send_close(hchannel);
1321 rc = fwdx_server_accept_options((char*)&sb[2],n-3);
1324 rc = fwdx_client_reply_options((char *)&sb[2],n-3);
1333 rc = 0; /* we don't recognize, not an error */
1340 p = (unsigned char *) &nchannel;
1342 /* IAC quoting has been stripped in tn_sb() */
1345 hchannel = ntohs(nchannel);
1346 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[hchannel].suspend =
1347 (sb[0] == FWDX_XOFF);
1352 return(rc < 0 ? -1 : 0);
1357 fwdx_send_xauth_to_xserver(int channel, unsigned char * data, int len)
1359 fwdx_send_xauth_to_xserver(channel, data, len)
1360 int channel; unsigned char * data; int len;
1361 #endif /* CK_ANSIC */
1363 int name_len, data_len, i;
1365 for (i = 0; i < MAXFWDX ; i++) {
1366 if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id == channel)
1372 if (!TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth)
1378 /* Parse the lengths of variable-length fields. */
1379 if (data[0] == 0x42) { /* byte order MSB first. */
1380 /* Xauth packets appear to always have this format */
1381 if ( data[1] != 0x00 ||
1388 name_len = (data[6] << 8) + data[7];
1389 data_len = (data[8] << 8) + data[9];
1390 } else if (data[0] == 0x6c) { /* Byte order LSB first. */
1391 /* Xauth packets appear to always have this format */
1392 if ( data[1] != 0x00 ||
1399 name_len = data[6] + (data[7] << 8);
1400 data_len = data[8] + (data[9] << 8);
1402 /* bad byte order byte */
1406 /* Check if the whole packet is in buffer. */
1407 if (len < 12 + ((name_len + 3) & ~3) + ((data_len + 3) & ~3))
1409 /* If the Telnet Server allows a real Xauth message to be sent */
1410 /* Then let the message be processed by the Xserver. */
1411 if (name_len + data_len > 0) {
1412 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
1416 /* If an empty Xauth message was received. We are going to */
1417 /* send our own Xauth message using the real Xauth data. And */
1418 /* then send any other data in the buffer. */
1420 int c, err, dpynum, scrnum, family, sb_len;
1421 char *display, *host = NULL, *rest = NULL;
1422 unsigned char *sb, *p;
1424 /* parse the local DISPLAY env var */
1425 display = getenv("DISPLAY");
1427 display = "127.0.0.1:0.0";
1429 if (fwdx_parse_displayname(display,
1430 &family, &host, &dpynum, &scrnum, &rest)) {
1431 char * disp_no = ckitoa(dpynum); /* should be unsigned */
1432 if (family == FamilyLocal) {
1433 /* call with address = "<local host name>" */
1434 char address[300] = "localhost";
1435 gethostname(address, sizeof(address) - 1);
1436 real_xauth = XauGetAuthByAddr(family,
1442 else if (family == FamilyInternet) {
1443 /* call with address = 4 bytes numeric ip addr (MSB) */
1445 if (hi = gethostbyname(host))
1446 real_xauth = XauGetAuthByAddr(family, 4,
1447 hi->h_addr, strlen(disp_no),
1451 if (host) free(host);
1452 if (rest) free(rest);
1454 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
1458 if (!strncmp(real_xauth->name,
1459 "MIT-MAGIC-COOKIE-1",
1460 real_xauth->name_length)) {
1463 name_len = real_xauth->name_length;
1466 if ( data[0] == 0x42 ) {
1467 msg[0] = 0x42; /* MSB order */
1468 msg[1] = msg[2] = 0;
1470 msg[4] = msg[5] = 0;
1471 msg[6] = (name_len >> 8);
1472 msg[7] = (name_len & 0xFF);
1473 msg[8] = (data_len >> 8);
1474 msg[9] = (data_len & 0xFF);
1476 msg[0] = 0x6c; /* LSB order */
1479 msg[3] = msg[4] = msg[5] = 0;
1480 msg[6] = (name_len & 0xFF);
1481 msg[7] = (name_len >> 8);
1482 msg[8] = (data_len & 0xFF);
1483 msg[9] = (data_len >> 8);
1485 msg[10] = msg[11] = 0;
1486 memcpy(&msg[12],real_xauth->name,18);
1487 msg[30] = msg[31] = 0;
1488 memcpy(&msg[32],real_xauth->data,16);
1490 if (fwdx_write_data_to_channel(channel,(char *)msg,48) < 0) {
1491 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
1494 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
1498 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
1499 return(0); /* we do not know how to handle this type yet */
1504 debug(F100,"fwdx_send_xauth_to_xserver error","",0);
1512 fwdx_authorize_channel(int channel, unsigned char * data, int len)
1514 fwdx_authorize_channel(channel, data, len)
1515 int channel; unsigned char * data; int len;
1516 #endif /* CK_ANSIC */
1518 /* XXX maybe we should have some retry handling if not the whole first
1519 * authorization packet arrives complete
1521 if ( !TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[channel].authorized ) {
1522 int name_len, data_len;
1527 /* Parse the lengths of variable-length fields. */
1528 if (data[0] == 0x42) { /* byte order MSB first. */
1529 /* Xauth packets appear to always have this format */
1530 if ( data[1] != 0x00 ||
1537 name_len = (data[6] << 8) + data[7];
1538 data_len = (data[8] << 8) + data[9];
1539 } else if (data[0] == 0x6c) { /* Byte order LSB first. */
1540 /* Xauth packets appear to always have this format */
1541 if ( data[1] != 0x00 ||
1548 name_len = data[6] + (data[7] << 8);
1549 data_len = data[8] + (data[9] << 8);
1551 /* bad byte order byte */
1554 /* Check if authentication protocol matches. */
1555 if (name_len != fake_xauth.name_length ||
1556 memcmp(data + 12, fake_xauth.name, name_len) != 0) {
1557 /* connection uses different authentication protocol */
1560 /* Check if authentication data matches our fake data. */
1561 if (data_len != fake_xauth.data_length ||
1562 memcmp(data + 12 + ((name_len + 3) & ~3),
1563 fake_xauth.data, fake_xauth.data_length) != 0) {
1564 /* auth data does not match fake data */
1567 /* substitute the fake data with real data if we have any */
1568 if (real_xauth && real_xauth->data)
1569 memcpy(data + 12 + ((name_len + 3) & ~3),
1570 real_xauth->data, data_len);
1572 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[channel].authorized = 1;
1578 #endif /* COMMENT */
1582 fwdx_send_close(int channel)
1584 fwdx_send_close(channel) int channel;
1585 #endif /* CK_ANSIC */
1587 unsigned short nchannel;
1592 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1597 nchannel = htons(channel);
1598 p = (unsigned char *) &nchannel;
1601 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
1602 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
1603 sb_out[i++] = TELOPT_FORWARD_X; /* Forward X */
1604 sb_out[i++] = FWDX_CLOSE; /* Open */
1605 sb_out[i++] = p[0]; /* First Byte of Channel */
1608 sb_out[i++] = p[1]; /* Second Byte of Channel */
1611 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
1612 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
1614 if (deblog || tn_deb || debses) {
1615 ckmakxmsg(fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
1616 TELOPT(TELOPT_FORWARD_X),
1617 " CLOSE CHANNEL=",ckitoa(channel)," IAC SE",
1618 NULL,NULL,NULL,NULL,NULL,NULL,NULL
1623 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1626 debug(F100,fwdx_msg_out,"",0);
1627 if (tn_deb || debses) tn_debug(fwdx_msg_out);
1629 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
1631 ReleaseTelnetMutex();
1640 fwdx_send_open(int channel)
1641 #else /* CK_ANSIC */
1642 fwdx_send_open(channel) int channel;
1643 #endif /* CK_ANSIC */
1645 unsigned short nchannel;
1650 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1655 nchannel = htons(channel);
1656 p = (unsigned char *) &nchannel;
1659 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
1660 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
1661 sb_out[i++] = TELOPT_FORWARD_X; /* Forward X */
1662 sb_out[i++] = FWDX_OPEN; /* Open */
1663 sb_out[i++] = p[0]; /* First Byte of Channel */
1666 sb_out[i++] = p[1]; /* Second Byte of Channel */
1669 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
1670 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
1672 if (deblog || tn_deb || debses) {
1673 ckmakxmsg(fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
1674 TELOPT(TELOPT_FORWARD_X),
1675 " OPEN CHANNEL=",ckitoa(channel)," IAC SE",
1676 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
1680 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1683 debug(F100,fwdx_msg_out,"",0);
1684 if (tn_deb || debses) tn_debug(fwdx_msg_out);
1686 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
1688 ReleaseTelnetMutex();
1697 fwdx_client_reply_options(char *opts, int n)
1699 fwdx_client_reply_options(opts, n) char *opts; int n;
1700 #endif /* CK_ANSIC */
1705 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1711 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
1712 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
1713 sb_out[i++] = TELOPT_FORWARD_X; /* Forward X */
1714 sb_out[i++] = FWDX_OPTIONS; /* Options */
1716 /* Look for the options we recognize and will support for this session */
1717 /* and reply with their bytes set */
1718 for (j=0; j<n; j++,i++) {
1719 sb_out[i] = FWDX_OPT_NONE; /* Add zero byte - no options */
1721 /* If we had any options to support, this is how we would do it */
1723 if (opts[j] & FWDX_OPT_XXXX) {
1724 /* set flag to remember option is in use */
1726 sb_out[i] |= FWDX_OPT_XXXX;
1729 #endif /* COMMENT */
1731 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
1732 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
1734 if (deblog || tn_deb || debses) {
1735 ckmakxmsg(fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
1736 TELOPT(TELOPT_FORWARD_X),
1737 " OPTIONS ",ckctox(sb_out[4],1)," IAC SE",
1738 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
1742 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1745 debug(F100,fwdx_msg_out,"",0);
1746 if (tn_deb || debses) tn_debug(fwdx_msg_out);
1748 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
1750 ReleaseTelnetMutex();
1759 fwdx_send_options() {
1763 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1769 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
1770 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
1771 sb_out[i++] = TELOPT_FORWARD_X; /* Forward X */
1772 sb_out[i++] = FWDX_OPTIONS; /* Options */
1773 sb_out[i] = FWDX_OPT_NONE;
1774 /* activate options here */
1776 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
1777 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
1780 if (deblog || tn_deb || debses) {
1781 ckmakmsg(fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
1782 TELOPT(TELOPT_FORWARD_X),
1783 " OPTIONS 00 IAC SE",NULL);
1787 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1790 debug(F100,fwdx_msg_out,"",0);
1791 if (tn_deb || debses) tn_debug(fwdx_msg_out);
1793 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
1795 ReleaseTelnetMutex();
1804 fwdx_send_data_from_channel(int channel, char * data, int len)
1806 fwdx_send_data_from_channel(channel, data, len)
1807 int channel; char * data; int len;
1810 unsigned short nchannel;
1811 /* static */ CHAR sb_priv[2048];
1813 int i, j, j_sav, rc;
1816 debug(F111,"fwdx_send_data_from_channel()","channel",channel);
1819 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1824 nchannel = htons(channel);
1825 p = (unsigned char *) &nchannel;
1828 sb_priv[j++] = (CHAR) IAC; /* I Am a Command */
1829 sb_priv[j++] = (CHAR) SB; /* Subnegotiation */
1830 sb_priv[j++] = TELOPT_FORWARD_X; /* Forward X */
1831 sb_priv[j++] = FWDX_DATA; /* Data */
1832 sb_priv[j++] = p[0]; /* First Byte of Channel */
1835 sb_priv[j++] = p[1]; /* Second Byte of Channel */
1840 for (i = 0; i < len; i++) {
1841 tmp = (unsigned int)data[i];
1848 if ( j >= 2045 && (i < len-1) ) {
1849 sb_priv[j++] = (CHAR) IAC; /* End of Subnegotiation */
1850 sb_priv[j++] = (CHAR) SE; /* marked by IAC SE */
1853 if (deblog || tn_deb || debses) {
1854 ckmakxmsg( fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
1855 TELOPT(TELOPT_FORWARD_X),
1856 " DATA CHANNEL=",ckitoa(channel)," ",
1857 NULL,NULL,NULL,NULL,NULL,NULL,NULL );
1858 tn_hex(fwdx_msg_out,TN_MSG_LEN,&sb_priv[j_sav],j-(j_sav+2));
1859 ckstrncat(fwdx_msg_out," IAC SE",TN_MSG_LEN);
1863 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1866 debug(F100,fwdx_msg_out,"",0);
1867 if (tn_deb || debses) tn_debug(fwdx_msg_out);
1869 rc = (ttol(sb_priv,j) < 0); /* Send it. */
1871 ReleaseTelnetMutex();
1874 debug(F110,"fwdx_send_data_from_channel()","ttol() failed",0);
1879 sb_priv[j++] = (CHAR) IAC; /* I Am a Command */
1880 sb_priv[j++] = (CHAR) SB; /* Subnegotiation */
1881 sb_priv[j++] = TELOPT_FORWARD_X; /* Forward X */
1882 sb_priv[j++] = FWDX_DATA; /* Data */
1883 sb_priv[j++] = p[0]; /* First Byte of Channel */
1886 sb_priv[j++] = p[1]; /* Second Byte of Channel */
1892 sb_priv[j++] = (CHAR) IAC; /* End of Subnegotiation */
1893 sb_priv[j++] = (CHAR) SE; /* marked by IAC SE */
1896 if (deblog || tn_deb || debses) {
1897 ckmakxmsg( fwdx_msg_out,TN_MSG_LEN,
1898 "TELNET SENT SB ",TELOPT(TELOPT_FORWARD_X),
1899 " DATA ",ckctox(p[0],1)," ",ckctox(p[1],1)," ",
1900 NULL,NULL,NULL,NULL,NULL);
1901 tn_hex(fwdx_msg_out,TN_MSG_LEN,&sb_priv[6],j-8);
1902 ckstrncat(fwdx_msg_out," IAC SE",TN_MSG_LEN);
1906 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1909 debug(F100,fwdx_msg_out,"",0);
1910 if (tn_deb || debses) tn_debug(fwdx_msg_out);
1912 rc = (ttol(sb_priv,j) < 0); /* Send it. */
1914 ReleaseTelnetMutex();
1917 debug(F110,"fwdx_send_data_from_channel()","ttol() failed",0);
1925 static unsigned char *
1927 fwdx_add_quoted_twobyte(unsigned char *p, unsigned short twobyte)
1929 fwdx_add_quoted_twobyte(p, twobyte)
1930 unsigned char *p; unsigned short twobyte;
1931 #endif /* CK_ANSIC */
1932 /* adds the IAC quoted (MSB) representation of 'channel' at buffer pointer 'p',
1933 * returning pointer to new buffer position. NO OVERFLOW CHECK!
1936 *p++ = (unsigned char)((twobyte >> 8) & 0xFF);
1937 if (*(p - 1) == 0xFF)
1939 *p++ = (unsigned char)(twobyte & 0xFF);
1940 if (*(p - 1) == 0xFF)
1947 fwdx_create_fake_xauth(char *name, int name_len, int data_len)
1949 fwdx_create_fake_xauth(name, name_len, data_len)
1950 char *name; int name_len; int data_len;
1951 #endif /* CK_ANSIC */
1953 char stackdata[256];
1956 if (!name_len || !data_len)
1958 fake_xauth.name = malloc(name_len);
1959 fake_xauth.data = malloc(data_len);
1960 if (!fake_xauth.name || !fake_xauth.data)
1962 fake_xauth.name_length = name_len;
1963 memcpy(fake_xauth.name, name, name_len);
1964 fake_xauth.data_length = data_len;
1966 /* try to make a random unsigned int to feed srand() */
1969 for (n = 0; n < sizeof(stackdata); n++)
1971 srand((unsigned int)c);
1972 for (c = 0; c < data_len; c++)
1973 fake_xauth.data[c] = (unsigned char)rand();
1978 /* No longer used */
1980 fwdx_send_xauth(void)
1982 int c, err, dpynum, family, sb_len, rc;
1983 char *display, *host = NULL;
1984 unsigned char *sb_priv, *p;
1986 /* parse the local DISPLAY env var */
1987 if (!(display = tn_get_display()))
1989 if (fwdx_parse_displayname(display, &family, &host, &dpynum, NULL, NULL)) {
1990 char * disp_no = ckitoa(dpynum);
1991 if (family == FamilyLocal) {
1992 /* call with address = "<local host name>" */
1993 char address[300] = "localhost";
1994 gethostname(address, sizeof(address) - 1);
1995 real_xauth = XauGetAuthByAddr(family,
2002 else if (family == FamilyInternet) {
2003 /* call with address = 4 bytes numeric ip addr (MSB) */
2005 if (hi = gethostbyname(host))
2006 real_xauth = XauGetAuthByAddr(family, 4,
2018 err = fwdx_create_fake_xauth(real_xauth->name,
2019 real_xauth->name_length,
2020 real_xauth->data_length
2023 err = fwdx_create_fake_xauth("MIT-MAGIC-COOKIE-1",
2024 strlen("MIT-MAGIC-COOKIE-1"), 16);
2028 /* allocate memory for the SB block, alloc for worst case */
2029 /* the following sprintf() calls are safe due to length checking */
2030 /* buffer is twice as big as the input just in case every byte was IAC */
2031 sb_len = 5 + 2 + 2 + fake_xauth.name_length + fake_xauth.data_length + 2;
2032 if (!(sb_priv = malloc(2 * sb_len)))
2035 sprintf(p, "%c%c%c%c%c", IAC, SB, TELOPT_FORWARD_X,
2036 FWDX_OPT_DATA, FWDX_OPT_XAUTH);
2038 p = fwdx_add_quoted_twobyte(p, fake_xauth.name_length);
2039 p = fwdx_add_quoted_twobyte(p, fake_xauth.data_length);
2040 for (c = 0; c < fake_xauth.name_length; c++) {
2041 *p++ = fake_xauth.name[c];
2042 if ((unsigned char)fake_xauth.name[c] == 0xFF)
2045 for (c = 0; c < fake_xauth.data_length; c++) {
2046 *p++ = fake_xauth.data[c];
2047 if ((unsigned char)fake_xauth.data[c] == 0xFF)
2050 sprintf(p, "%c%c", IAC, SE);
2054 if (deblog || tn_deb || debses) {
2055 sprintf(fwdx_msg_out,"TELNET SENT SB %s OPTION_DATA XAUTH ",
2056 TELOPT(TELOPT_FORWARD_X));
2057 tn_hex(fwdx_msg_out,TN_MSG_LEN,&sb_priv[5],(p-sb_priv)-7);
2058 ckstrncat(fwdx_msg_out," IAC SE",TN_MSG_LEN);
2062 /* Add Telnet Debug info here */
2064 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
2067 debug(F100,fwdx_msg_out,"",0);
2068 if (tn_deb || debses) tn_debug(fwdx_msg_out);
2070 rc = ( ttol(sb_priv,p-sb_priv) < 0 ); /* Send it. */
2072 ReleaseTelnetMutex();
2075 debug(F110,"fwdx_send_xauth()","ttol() failed",0);
2083 #endif /* COMMENT */
2085 /* Only if we ever become a server - not yet ported to Kermit */
2086 /* And even so most of this code does not belong in this module */
2089 fwdx_write_xauthfile(void)
2091 int dpynum, scrnum, family;
2092 char myhost[300], *host, *rest = NULL;
2094 struct sockaddr_in saddr;
2097 if (!fwdx_display && !fwdx_xauthfile)
2099 if (!parse_displayname(fwdx_display,
2100 &family, &host, &dpynum, &scrnum, &rest))
2102 if (rest) free(rest);
2103 if (host) free(host);
2104 if (family != FamilyInternet)
2105 return 3; /* every thing but FamilyInternet is unexpected */
2107 /* X connections to localhost:1 is actually treated as local unix sockets,
2108 * see the 'xauth' man page.
2110 xauth.family = FamilyLocal;
2111 if (gethostname(myhost, sizeof(myhost) - 1))
2113 xauth.address_length = strlen(myhost);
2114 if (!(xauth.address = malloc(xauth.address_length)))
2116 memcpy(xauth.address, myhost, xauth.address_length);
2118 /* the display number is written as a string, not numeric */
2119 if (!(xauth.number = malloc(6)))
2121 snprintf(xauth.number, 5, "%u", dpynum);
2122 xauth.number_length = strlen(xauth.number);
2123 if (!(file = fopen(fwdx_xauthfile, "wb")))
2125 if (!XauWriteAuth(file, &xauth))
2128 setenv("XAUTHORITY", fwdx_xauthfile, 1);
2133 fwdx_setup_xauth(unsigned char *sp, int len)
2134 /* called with 'len' xauth bytes, starting at 'sp'
2135 * the data format is: <uint16 name_length> <uint16 data_length> <name> <data>
2140 if (!fwdx_options[FWDX_OPT_XAUTH])
2145 /* setup the xauth struct */
2146 xauth.name_length = (sp[0] << 8) + sp[1];
2147 xauth.data_length = (sp[2] << 8) + sp[3];
2148 if (len != 4 + xauth.name_length + xauth.data_length)
2150 xauth.name = malloc(xauth.name_length);
2151 xauth.data = malloc(xauth.data_length);
2152 if (!xauth.name || !xauth.data)
2154 memcpy(xauth.name, sp + 4, xauth.name_length);
2155 memcpy(xauth.data, sp + 4 + xauth.name_length, xauth.data_length);
2157 /* Setup to always have a local .Xauthority. */
2158 fwdx_xauthfile = malloc(MAXPATHLEN+1);
2159 snprintf(fwdx_xauthfile, MAXPATHLEN, "/tmp/XauthXXXXXX");
2160 if ((xauthfd = mkstemp(fwdx_xauthfile)) != -1)
2161 /* we change file ownership later, when we know who is to be owner! */
2164 free(fwdx_xauthfile);
2165 fwdx_xauthfile = NULL;
2168 /* Must have the subshell's new DISPLAY env var to write xauth to xauthfile */
2170 if (fwdx_write_xauthfile())
2176 void fwdx_set_xauthfile_owner(int uid)
2180 if (!fwdx_xauthfile || !(pwd = getpwuid(uid)))
2182 chown(fwdx_xauthfile, pwd->pw_uid, pwd->pw_gid);
2186 fwdx_server_accept_options(unsigned char *sp, int len)
2187 /* called with 'len' option bytes, starting at 'sp' */
2191 for (c = 0; c < len-2; c++) {
2193 if (sp[c] & FWDX_OPT_XAUTH)
2199 #endif /* FWDX_SERVER */
2200 #endif /* CK_FORWARD_X */
2204 iks_wait() -- Wait for an IKS subnegotiation response.
2205 sb - is either KERMIT_REQ_START or KERMIT_REQ_STOP depending on the desired
2206 state of the peer's Kermit server.
2207 flushok - specifies whether it is ok to throw away non-Telnet data
2208 if so, then we call ttflui() instead of tn_flui().
2210 1 if the desired state is achieved or if it is unknown.
2211 0 if the desired state is not achieved.
2215 iks_wait(int sb, int flushok)
2216 #else /* CK_ANSIC */
2217 iks_wait(sb,flushok) int sb; int flushok;
2218 #endif /* CK_ANSIC */
2220 int tn_wait_save = tn_wait_flg;
2223 if (TELOPT_U(TELOPT_KERMIT)) {
2225 case KERMIT_REQ_START:
2227 "iks_wait KERMIT_REQ_START",
2229 TELOPT_SB(TELOPT_KERMIT).kermit.u_start
2231 tn_siks(KERMIT_REQ_START);
2232 tn_wait_flg = 1; /* Kermit Option MUST wait */
2236 x = tn_wait("iks_wait() me_iks_req_start");
2237 } while (x == 0 && flushok && tn_wait_idx == TN_WAIT_BUF_SZ);
2238 tn_wait_flg = tn_wait_save;
2241 if (tn_wait_idx == TN_WAIT_BUF_SZ) {
2243 * We are attempting to start a kermit server on the peer
2244 * the most likely reason is because we want to perform a
2245 * file transfer. But there is a huge amount of non telnet
2246 * negotiation data coming in and so we have not been able
2247 * to find the response. So we will lie and assume that
2248 * response is 'yes'. The worse that will happen is that
2249 * a RESP_STOP is received after we enter protocol mode.
2250 * And the protocol operation will be canceled.
2256 return(TELOPT_SB(TELOPT_KERMIT).kermit.u_start);
2258 case KERMIT_REQ_STOP:
2260 "iks_wait KERMIT_REQ_STOP",
2262 TELOPT_SB(TELOPT_KERMIT).kermit.u_start
2264 tn_siks(KERMIT_REQ_STOP);
2265 tn_wait_flg = 1; /* Kermit Option MUST wait */
2269 x = tn_wait("iks_wait() me_iks_req_stop");
2270 } while (x == 0 && flushok && tn_wait_idx == TN_WAIT_BUF_SZ);
2271 tn_wait_flg = tn_wait_save;
2275 if (tn_wait_idx == TN_WAIT_BUF_SZ) {
2277 * We are attempting to stop a kermit server on the peer
2278 * the most likely reason being that we want to enter
2279 * CONNECT mode. But there is a huge amount of non telnet
2280 * negotiation data coming in and so we have not been able
2281 * to find the response. So we will lie and assume that
2282 * the answer is 'yes' and allow the CONNECT command to
2283 * succeed. The worst that happens is that CONNECT mode
2284 * swallows the incoming data displaying it to the user
2285 * and then it resumes Kermit client mode.
2291 return(!TELOPT_SB(TELOPT_KERMIT).kermit.u_start);
2301 iks_tn_sb(CHAR * sb, int n)
2303 iks_tn_sb(sb, n) CHAR * sb; int n;
2304 #endif /* CK_ANSIC */
2310 int inautodl = 0, cmdadl = 1;
2313 extern int autodl, inautodl, cmdadl;
2314 #endif /* CK_AUTODL */
2317 case KERMIT_START: /* START */
2318 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 1;
2321 case KERMIT_STOP: /* STOP */
2322 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
2325 case KERMIT_REQ_START: /* REQ-START */
2329 cmdadl = 1; /* Turn on packet detection */
2330 #endif /* CK_AUTODL */
2331 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
2332 tn_siks(KERMIT_RESP_START);
2333 } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
2334 tn_siks(KERMIT_RESP_START);
2339 if (local && (IsConnectMode() && autodl) ||
2340 (!IsConnectMode() &&
2341 (inautodl || sstate == 'x' || sstate == 'v'))
2343 tn_siks(KERMIT_RESP_START); /* START */
2347 if ((local && what == W_CONNECT && autodl) ||
2348 (local && what != W_CONNECT &&
2349 (inautodl || sstate == 'x' || sstate == 'v')
2351 tn_siks(KERMIT_RESP_START); /* START */
2354 #endif /* CK_AUTODL */
2355 #endif /* IKSDONLY */
2356 tn_siks(KERMIT_RESP_STOP);
2359 tn_siks(KERMIT_RESP_STOP);
2363 case KERMIT_REQ_STOP: /* REQ-STOP */
2364 /* The protocol requires that the request be responded to */
2365 /* either by changing states or by reporting the current */
2368 /* We need to provide the user some way of dictating what */
2369 /* the policies should be. For instance, if we are in */
2370 /* CONNECT mode with autodownload ON and we get a REQ-STOP*/
2371 /* what should the proper response be? */
2376 #endif /* CK_AUTODL */
2379 cmdadl = 0; /* Turn off packet detection */
2380 #endif /* CK_AUTODL */
2381 tn_siks(KERMIT_RESP_STOP);
2382 } else if (server) {
2384 if (en_fin) { /* If the server is allowed to stop */
2385 tn_siks(KERMIT_RESP_STOP);
2386 } else { /* We are not allowed to stop */
2387 tn_siks(KERMIT_RESP_START);
2393 else if (local && (IsConnectMode() && autodl) ||
2394 (!IsConnectMode() && inautodl)
2396 /* If we are a pseudo-server and the other side requests */
2397 /* that we stop, tell then that we have even though we */
2398 /* have not. Otherwise, the other side might refuse to */
2399 /* enter SERVER mode. */
2401 tn_siks(KERMIT_RESP_STOP); /* STOP */
2404 else if ((local && what == W_CONNECT && autodl) ||
2405 (local && what != W_CONNECT && inautodl)
2407 /* If we are a pseudo-server and the other side requests */
2408 /* that we stop, tell then that we have even though we */
2409 /* have not. Otherwise, the other side might refuse to */
2410 /* enter SERVER mode. */
2412 tn_siks(KERMIT_RESP_STOP); /* STOP */
2415 #endif /* CK_AUTODL */
2416 #endif /* IKSDONLY */
2420 /* If we are not currently in any mode that accepts */
2421 /* Kermit packets then of course report that we are */
2422 /* not being a Kermit server. */
2424 tn_siks(KERMIT_RESP_STOP); /* STOP */
2428 case KERMIT_SOP: { /* SOP */
2430 extern CHAR stchr; /* Incoming SOP character */
2433 TELOPT_SB(TELOPT_KERMIT).kermit.sop = 1;
2437 case KERMIT_RESP_START: /* START */
2438 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 1;
2439 if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start) {
2440 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
2441 } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop) {
2442 /* If we have issued a request to stop a Kermit Server */
2443 /* and the response is Start, then we must report this */
2444 /* to the caller. */
2445 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
2449 case KERMIT_RESP_STOP: /* STOP */
2450 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
2451 if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start) {
2452 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
2453 /* If we have issued a request to start a Kermit Server */
2454 /* and the response is Stop, then we must report this */
2455 /* to the caller. */
2456 } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop) {
2457 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
2464 } /* switch (sb[0]) */
2466 #endif /* IKS_OPTION */
2468 /* Initialize telnet settings - set default values for ME and U modes */
2474 #endif /* CK_FORWARD_X */
2475 #ifdef CK_ENVIRONMENT
2478 for (i = 0; i < 8; i++) {
2479 tn_env_uservar[i][0] = NULL;
2480 tn_env_uservar[i][1] = NULL;
2483 #endif /* CK_ENVIRONMENT */
2485 /* initialize all options to refuse in both directions */
2486 for (opt = 0; opt < NTELOPTS; opt++) {
2489 TELOPT_UNANSWERED_WILL(opt) = 0;
2490 TELOPT_UNANSWERED_DO(opt) = 0;
2491 TELOPT_UNANSWERED_WONT(opt) = 0;
2492 TELOPT_UNANSWERED_DONT(opt) = 0;
2493 TELOPT_UNANSWERED_SB(opt) = 0;
2494 TELOPT_ME_MODE(opt) = TN_NG_RF;
2495 TELOPT_U_MODE(opt) = TN_NG_RF;
2496 TELOPT_DEF_S_ME_MODE(opt) = TN_NG_RF;
2497 TELOPT_DEF_S_U_MODE(opt) = TN_NG_RF;
2498 TELOPT_DEF_C_ME_MODE(opt) = TN_NG_RF;
2499 TELOPT_DEF_C_U_MODE(opt) = TN_NG_RF;
2500 for (cmd = 0; cmd < 4; cmd ++)
2501 tncnts[TELOPT_INDEX(opt)][cmd] = 0;
2504 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
2505 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
2506 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
2507 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
2508 TELOPT_SB(TELOPT_KERMIT).kermit.sop = 0;
2509 #endif /* IKS_OPTION */
2511 #ifdef CK_ENCRYPTION
2512 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
2513 #endif /* CK_ENCRYPTION */
2516 TELOPT_SB(TELOPT_NAWS).naws.x = 0;
2517 TELOPT_SB(TELOPT_NAWS).naws.y = 0;
2518 #endif /* CK_NAWS */
2521 TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 0;
2522 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 0;
2523 TELOPT_SB(TELOPT_START_TLS).start_tls.auth_request = 0;
2526 /* Now set the ones we want to accept to the proper values */
2527 TELOPT_DEF_S_ME_MODE(TELOPT_SGA) = TN_NG_RQ;
2528 TELOPT_DEF_S_U_MODE(TELOPT_SGA) = TN_NG_RQ;
2529 TELOPT_DEF_C_ME_MODE(TELOPT_SGA) = TN_NG_AC;
2530 TELOPT_DEF_C_U_MODE(TELOPT_SGA) = TN_NG_AC;
2532 TELOPT_DEF_S_ME_MODE(TELOPT_BINARY) = TN_NG_AC;
2533 TELOPT_DEF_S_U_MODE(TELOPT_BINARY) = TN_NG_AC;
2534 TELOPT_DEF_C_ME_MODE(TELOPT_BINARY) = TN_NG_AC;
2535 TELOPT_DEF_C_U_MODE(TELOPT_BINARY) = TN_NG_AC;
2537 TELOPT_DEF_S_ME_MODE(TELOPT_LOGOUT) = TN_NG_AC;
2538 TELOPT_DEF_S_U_MODE(TELOPT_LOGOUT) = TN_NG_AC;
2539 TELOPT_DEF_C_ME_MODE(TELOPT_LOGOUT) = TN_NG_AC;
2540 TELOPT_DEF_C_U_MODE(TELOPT_LOGOUT) = TN_NG_AC;
2543 TELOPT_DEF_S_ME_MODE(TELOPT_KERMIT) = TN_NG_RQ;
2544 TELOPT_DEF_S_U_MODE(TELOPT_KERMIT) = TN_NG_RQ;
2545 TELOPT_DEF_C_ME_MODE(TELOPT_KERMIT) = TN_NG_RQ;
2546 TELOPT_DEF_C_U_MODE(TELOPT_KERMIT) = TN_NG_RQ;
2547 #endif /* IKS_OPTION */
2549 #ifdef CK_ENCRYPTION
2550 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
2551 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
2552 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
2553 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
2554 #endif /* CK_ENCRYPTION */
2556 TELOPT_DEF_S_ME_MODE(TELOPT_ECHO) = TN_NG_RQ;
2560 TELOPT_DEF_S_U_MODE(TELOPT_TTYPE) = TN_NG_RQ;
2562 #ifdef CK_ENVIRONMENT
2563 TELOPT_DEF_S_U_MODE(TELOPT_NEWENVIRON) = TN_NG_RQ;
2564 #endif /* CK_ENVIRONMENT */
2566 #ifdef CK_AUTHENTICATION
2567 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
2568 #endif /* CK_AUTHENTICATION */
2571 if (ck_ssleay_is_installed()) {
2572 TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RQ;
2573 TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = TN_NG_AC;
2578 TELOPT_DEF_S_U_MODE(TELOPT_NAWS) = TN_NG_RQ;
2579 #endif /* CK_NAWS */
2581 TELOPT_DEF_C_U_MODE(TELOPT_ECHO) = TN_NG_AC;
2582 TELOPT_DEF_C_ME_MODE(TELOPT_TTYPE) = TN_NG_RQ;
2584 #ifdef CK_ENVIRONMENT
2585 TELOPT_DEF_C_ME_MODE(TELOPT_NEWENVIRON) = TN_NG_RQ;
2586 #endif /* CK_ENVIRONMENT */
2588 #ifdef CK_AUTHENTICATION
2589 TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
2590 #endif /* CK_AUTHENTICATION */
2593 TELOPT_DEF_C_ME_MODE(TELOPT_NAWS) = TN_NG_RQ;
2594 #endif /* CK_NAWS */
2597 TELOPT_DEF_C_ME_MODE(TELOPT_SNDLOC) = TN_NG_RQ;
2598 #endif /* CK_SNDLOC */
2601 TELOPT_DEF_C_U_MODE(TELOPT_FORWARD_X) = TN_NG_AC;
2602 TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket = -1;
2603 for (x = 0; x < MAXFWDX; x++) {
2604 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd = -1;
2605 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].id = -1;
2606 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].need_to_send_xauth = 0;
2607 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].suspend = 0;
2609 #endif /* CK_FORWARD_X */
2612 TELOPT_DEF_C_ME_MODE(TELOPT_COMPORT) = TN_NG_RQ;
2613 #endif /* TN_COMPORT */
2615 /* Set the initial values for currently known mode */
2616 for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
2617 if (TELOPT_OK(opt)) {
2618 TELOPT_ME_MODE(opt) = sstelnet ?
2619 TELOPT_DEF_S_ME_MODE(opt) :
2620 TELOPT_DEF_C_ME_MODE(opt);
2621 TELOPT_U_MODE(opt) = sstelnet ?
2622 TELOPT_DEF_S_U_MODE(opt) :
2623 TELOPT_DEF_C_U_MODE(opt);
2630 /* Send Delayed Subnegotiations */
2634 if (TELOPT_SB(TELOPT_TTYPE).term.need_to_send) {
2636 TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 0;
2638 #ifdef CK_ENVIRONMENT
2639 if (TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send &&
2640 TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
2641 tn_snenv((CHAR *)TELOPT_SB(TELOPT_NEWENVIRON).env.str,
2642 TELOPT_SB(TELOPT_NEWENVIRON).env.len);
2643 free(TELOPT_SB(TELOPT_NEWENVIRON).env.str);
2644 TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
2645 TELOPT_SB(TELOPT_NEWENVIRON).env.len=0;
2646 TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 0;
2649 if (TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send) {
2651 TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 0;
2653 #endif /* CK_XDISPLOC */
2654 #endif /* CK_ENVIRONMENT */
2656 if (TELOPT_SB(TELOPT_NAWS).naws.need_to_send) {
2658 TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 0;
2660 #endif /* CK_NAWS */
2662 if (TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send) {
2664 TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 0;
2666 #endif /* CK_SNDLOC */
2668 if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send) {
2670 fwdx_send_options();
2671 TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 0;
2673 #endif /* CK_FORWARD_X */
2675 if (TELOPT_SB(TELOPT_COMPORT).comport.need_to_send) {
2677 TELOPT_SB(TELOPT_COMPORT).comport.need_to_send = 0;
2679 #endif /* TN_COMPORT */
2687 tn_wait_idx = 0; /* Clear the tn_push() buffer */
2688 tn_wait_tmo = TN_TIMEOUT; /* Reset wait timer stats */
2692 /* Reset the TELNET OPTIONS counts */
2693 for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
2694 if (TELOPT_OK(opt)) {
2697 TELOPT_UNANSWERED_WILL(opt) = 0;
2698 TELOPT_UNANSWERED_DO(opt) = 0;
2699 TELOPT_UNANSWERED_WONT(opt) = 0;
2700 TELOPT_UNANSWERED_DONT(opt) = 0;
2701 TELOPT_UNANSWERED_SB(opt) = 0;
2702 TELOPT_ME_MODE(opt) = sstelnet ?
2703 TELOPT_DEF_S_ME_MODE(opt) :
2704 TELOPT_DEF_C_ME_MODE(opt);
2705 TELOPT_U_MODE(opt) = sstelnet ?
2706 TELOPT_DEF_S_U_MODE(opt) :
2707 TELOPT_DEF_C_U_MODE(opt);
2711 switch (TELOPT_ME_MODE(opt)) {
2713 debug(F110,"tn_ini ME REFUSE ",TELOPT(opt),0);
2716 debug(F110,"tn_ini ME ACCEPT ",TELOPT(opt),0);
2719 debug(F110,"tn_ini ME REQUEST",TELOPT(opt),0);
2722 debug(F110,"tn_ini ME REQUIRE",TELOPT(opt),0);
2725 switch (TELOPT_U_MODE(opt)) {
2727 debug(F110,"tn_ini U REFUSE ",TELOPT(opt),0);
2730 debug(F110,"tn_ini U ACCEPT ",TELOPT(opt),0);
2733 debug(F110,"tn_ini U REQUEST",TELOPT(opt),0);
2736 debug(F110,"tn_ini U REQUIRE",TELOPT(opt),0);
2741 for (cmd = 0; cmd < 4; cmd ++)
2742 tncnts[TELOPT_INDEX(opt)][cmd] = 0;
2745 #ifdef CK_ENVIRONMENT
2747 TELOPT_ME_MODE(TELOPT_NEWENVIRON) = TN_NG_RF;
2748 TELOPT_U_MODE(TELOPT_NEWENVIRON) = TN_NG_RF;
2750 #endif /* CK_ENVIRONMENT */
2753 TELOPT_DEF_C_ME_MODE(TELOPT_SNDLOC) = TN_NG_RF;
2754 #endif /* CK_SNDLOC */
2756 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
2757 TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
2758 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
2759 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
2760 TELOPT_SB(TELOPT_KERMIT).kermit.sop = 0;
2761 #endif /* IKS_OPTION */
2762 #ifdef CK_ENCRYPTION
2763 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
2764 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 0;
2765 #endif /* CK_ENCRYPTION */
2767 TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 0;
2768 TELOPT_SB(TELOPT_NAWS).naws.x = 0;
2769 TELOPT_SB(TELOPT_NAWS).naws.y = 0;
2770 #endif /* CK_NAWS */
2771 TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 0;
2772 TELOPT_SB(TELOPT_TTYPE).term.type[0] = '\0';
2773 #ifdef CK_ENVIRONMENT
2774 TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 0;
2776 TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
2777 else if (TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
2778 free(TELOPT_SB(TELOPT_NEWENVIRON).env.str);
2779 TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
2781 TELOPT_SB(TELOPT_NEWENVIRON).env.len=0;
2783 TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 0;
2784 #endif /* CK_XDISPLOC */
2785 #endif /* CK_ENVIRONMENT */
2787 TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 0;
2788 #endif /* CK_SNDLOC */
2790 TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 0;
2791 TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket = -1;
2792 for (x = 0; x < MAXFWDX; x++) {
2793 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd = -1;
2794 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].id = -1;
2795 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].need_to_send_xauth = 0;
2796 TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].suspend = 0;
2798 /* Reset Xauth data */
2800 XauDisposeAuth(real_xauth);
2803 if ( fake_xauth.name )
2804 free(fake_xauth.name);
2805 if ( fake_xauth.data )
2806 free(fake_xauth.data);
2807 if ( fake_xauth.address )
2808 free(fake_xauth.address);
2809 if ( fake_xauth.number )
2810 free(fake_xauth.number);
2811 memset(&fake_xauth,0,sizeof(fake_xauth));
2813 TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 0;
2815 #endif /* CK_FORWARD_X */
2817 if (tls_only_flag || ssl_only_flag) {
2818 TELOPT_ME_MODE(TELOPT_START_TLS) = TN_NG_RF;
2819 TELOPT_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
2821 TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 0;
2822 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 0;
2823 TELOPT_SB(TELOPT_START_TLS).start_tls.auth_request = 0;
2826 #ifdef CK_ENCRYPTION
2827 if (!ck_crypt_is_installed()
2829 || tls_only_flag || ssl_only_flag
2832 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2833 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2835 #endif /* CK_ENCRYPTION */
2838 TELOPT_SB(TELOPT_COMPORT).comport.need_to_send = 0;
2839 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
2840 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms = 0;
2842 #endif /* TN_COMPORT */
2844 tn_first = 0; /* No longer the first time init */
2847 ttnum = -1; /* Reset TermType negotiation */
2858 if (tn_init && tn_begun)
2862 debug(F111,"tn_start","sstelnet",sstelnet);
2865 oldplex = duplex; /* save old duplex value */
2866 duplex = 1; /* and set to half duplex for telnet */
2869 if (!TELOPT_ME(TELOPT_START_TLS) &&
2870 TELOPT_ME_MODE(TELOPT_START_TLS) >= TN_NG_RQ) {
2871 if (tn_sopt(WILL, TELOPT_START_TLS) < 0)
2873 TELOPT_UNANSWERED_WILL(TELOPT_START_TLS) = 1;
2876 if (!TELOPT_U(TELOPT_START_TLS) &&
2877 TELOPT_U_MODE(TELOPT_START_TLS) >= TN_NG_RQ) {
2878 if (tn_sopt(DO, TELOPT_START_TLS) < 0)
2880 TELOPT_UNANSWERED_DO(TELOPT_START_TLS) = 1;
2885 #ifdef CK_AUTHENTICATION
2886 debug(F110,"tn_ini() CK_AUTHENTICATION","",0);
2887 if (tn_init) /* tn_ini() might be called recursively */
2889 if (!TELOPT_ME(TELOPT_AUTHENTICATION) &&
2890 TELOPT_ME_MODE(TELOPT_AUTHENTICATION) >= TN_NG_RQ) {
2891 if (tn_sopt(WILL, TELOPT_AUTHENTICATION) < 0)
2893 TELOPT_UNANSWERED_WILL(TELOPT_AUTHENTICATION) = 1;
2896 if (!TELOPT_U(TELOPT_AUTHENTICATION) &&
2897 TELOPT_U_MODE(TELOPT_AUTHENTICATION) >= TN_NG_RQ) {
2898 if (tn_sopt(DO, TELOPT_AUTHENTICATION) < 0)
2900 TELOPT_UNANSWERED_DO(TELOPT_AUTHENTICATION) = 1;
2903 #ifdef CK_ENCRYPTION
2904 if (TELOPT_U_MODE(TELOPT_AUTHENTICATION) == TN_NG_RF &&
2905 TELOPT_ME_MODE(TELOPT_AUTHENTICATION) == TN_NG_RF) {
2906 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2907 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2909 #endif /* CK_ENCRYPTION */
2910 #endif /* CK_AUTHENTICATION */
2914 debug(F110,"tn_ini() CK_NAWS !NOLOCAL","",0);
2916 /* Console terminal screen rows and columns */
2921 VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0)
2923 debug(F101,"tn_ini tt_cols 1","",VscrnGetWidth(VTERM));
2925 if (VscrnGetWidth(VTERM) < 0 ||
2926 VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0) < 0) {
2927 ttgwsiz(); /* Try to find out */
2932 VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0)
2934 debug(F101,"tn_ini tt_cols 2","",VscrnGetWidth(VTERM));
2935 /* Now do we know? */
2936 if (VscrnGetWidth(VTERM) > 0 &&
2937 VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0) > 0) {
2938 if (!TELOPT_ME(TELOPT_NAWS) &&
2939 TELOPT_ME_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
2940 if (tn_sopt(WILL, TELOPT_NAWS) < 0)
2942 TELOPT_UNANSWERED_WILL(TELOPT_NAWS) = 1;
2947 debug(F101,"tn_ini tt_rows 1","",tt_rows);
2948 debug(F101,"tn_ini tt_cols 1","",tt_cols);
2949 if (tt_rows < 0 || tt_cols < 0) { /* Not known yet */
2950 ttgwsiz(); /* Try to find out */
2952 debug(F101,"tn_ini tt_rows 2","",tt_rows);
2953 debug(F101,"tn_ini tt_cols 2","",tt_cols);
2954 if (tt_rows > 0 && tt_cols > 0) { /* Now do we know? */
2955 if (!TELOPT_ME(TELOPT_NAWS) &&
2956 TELOPT_ME_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
2957 if (tn_sopt(WILL, TELOPT_NAWS) < 0)
2959 TELOPT_UNANSWERED_WILL(TELOPT_NAWS) = 1;
2965 #endif /* NOLOCAL */
2967 if (!TELOPT_U(TELOPT_NAWS) &&
2968 TELOPT_U_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
2969 if (tn_sopt(DO, TELOPT_NAWS) < 0)
2971 TELOPT_UNANSWERED_DO(TELOPT_NAWS) = 1;
2975 #endif /* CK_NAWS */
2977 if (!TELOPT_ME(TELOPT_SGA) &&
2978 TELOPT_ME_MODE(TELOPT_SGA) >= TN_NG_RQ) {
2979 if (tn_sopt(WILL, TELOPT_SGA) < 0)
2981 TELOPT_UNANSWERED_WILL(TELOPT_SGA) = 1;
2984 if (!TELOPT_U(TELOPT_SGA) &&
2985 TELOPT_U_MODE(TELOPT_SGA) >= TN_NG_RQ) {
2986 if (tn_sopt(DO, TELOPT_SGA) < 0)
2988 TELOPT_UNANSWERED_DO(TELOPT_SGA) = 1;
2992 if (!TELOPT_U(TELOPT_ECHO) &&
2993 TELOPT_U_MODE(TELOPT_ECHO) >= TN_NG_RQ) {
2994 if (tn_sopt(DO, TELOPT_ECHO) < 0)
2996 TELOPT_UNANSWERED_DO(TELOPT_ECHO) = 1;
3000 if (!TELOPT_ME(TELOPT_ECHO) &&
3001 TELOPT_ME_MODE(TELOPT_ECHO) >= TN_NG_RQ) {
3002 if (tn_sopt(WILL, TELOPT_ECHO) < 0)
3004 TELOPT_UNANSWERED_WILL(TELOPT_ECHO) = 1;
3008 debug(F100,"tn_ini about to send WILL TTYPE if requested","",0);
3010 Talking to TELNET port, so send WILL TERMINAL TYPE and DO SGA.
3011 Also send WILL NAWS if we know our screen dimensions.
3013 if (!TELOPT_ME(TELOPT_TTYPE) &&
3014 TELOPT_ME_MODE(TELOPT_TTYPE) >= TN_NG_RQ) {
3015 if ((x = tn_sopt(WILL,TELOPT_TTYPE)) < 0) {
3016 debug(F101,"tn_ini tn_sopt WILL TTYPE failed","",x);
3019 TELOPT_UNANSWERED_WILL(TELOPT_TTYPE) = 1;
3021 debug(F100,"tn_ini sent WILL TTYPE ok","",0);
3023 if (!TELOPT_U(TELOPT_TTYPE) &&
3024 TELOPT_U_MODE(TELOPT_TTYPE) >= TN_NG_RQ) {
3025 if ((x = tn_sopt(DO,TELOPT_TTYPE)) < 0) {
3026 debug(F101,"tn_ini tn_sopt DO TTYPE failed","",x);
3029 TELOPT_UNANSWERED_DO(TELOPT_TTYPE) = 1;
3031 debug(F100,"tn_ini sent DO TTYPE ok","",0);
3033 if (!TELOPT_ME(TELOPT_BINARY) &&
3034 TELOPT_ME_MODE(TELOPT_BINARY) >= TN_NG_RQ) {
3035 if (tn_sopt(WILL, TELOPT_BINARY) < 0)
3037 TELOPT_UNANSWERED_WILL(TELOPT_BINARY) = 1;
3040 if (!TELOPT_U(TELOPT_BINARY) &&
3041 TELOPT_U_MODE(TELOPT_BINARY) >= TN_NG_RQ) {
3042 if (tn_sopt(DO, TELOPT_BINARY) < 0)
3044 TELOPT_UNANSWERED_DO(TELOPT_BINARY) = 1;
3049 if (!TELOPT_ME(TELOPT_SNDLOC) &&
3050 TELOPT_ME_MODE(TELOPT_SNDLOC) >= TN_NG_RQ) {
3051 if (tn_sopt(WILL, TELOPT_SNDLOC) < 0)
3053 TELOPT_UNANSWERED_WILL(TELOPT_SNDLOC) = 1;
3057 #endif /* CK_SNDLOC */
3058 #ifdef CK_ENVIRONMENT
3060 if (!TELOPT_U(TELOPT_FORWARD_X) &&
3061 TELOPT_U_MODE(TELOPT_FORWARD_X) >= TN_NG_RQ) {
3062 if (tn_sopt(WILL, TELOPT_FORWARD_X) < 0)
3064 TELOPT_UNANSWERED_WILL(TELOPT_FORWARD_X) = 1;
3067 #endif /* FORWARD_X */
3069 if (!TELOPT_ME(TELOPT_XDISPLOC) &&
3070 TELOPT_ME_MODE(TELOPT_XDISPLOC) >= TN_NG_RQ) {
3071 if (tn_sopt(WILL, TELOPT_XDISPLOC) < 0)
3073 TELOPT_UNANSWERED_WILL(TELOPT_XDISPLOC) = 1;
3076 #endif /* CK_XDISPLOC */
3077 /* Will send terminal environment. */
3078 if (!TELOPT_ME(TELOPT_NEWENVIRON) &&
3079 TELOPT_ME_MODE(TELOPT_NEWENVIRON) >= TN_NG_RQ) {
3080 if (tn_sopt(WILL, TELOPT_NEWENVIRON) < 0)
3082 TELOPT_UNANSWERED_WILL(TELOPT_NEWENVIRON) = 1;
3085 if (!TELOPT_U(TELOPT_NEWENVIRON) &&
3086 TELOPT_U_MODE(TELOPT_NEWENVIRON) >= TN_NG_RQ) {
3087 if (tn_sopt(DO, TELOPT_NEWENVIRON) < 0)
3089 TELOPT_UNANSWERED_DO(TELOPT_NEWENVIRON) = 1;
3092 #endif /* CK_ENVIRONMENT */
3094 /* Take care of any other telnet options that require handling. */
3096 for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
3098 case TELOPT_AUTHENTICATION:
3099 case TELOPT_ENCRYPTION:
3103 case TELOPT_NEWENVIRON:
3105 case TELOPT_XDISPLOC:
3109 case TELOPT_START_TLS:
3110 case TELOPT_FORWARD_X:
3114 if (TELOPT_OK(opt)) {
3115 if (!TELOPT_ME(opt) &&
3116 TELOPT_ME_MODE(opt) >= TN_NG_RQ) {
3117 if (tn_sopt(WILL, opt) < 0)
3119 TELOPT_UNANSWERED_WILL(opt) = 1;
3122 if (!TELOPT_U(opt) &&
3123 TELOPT_U_MODE(opt) >= TN_NG_RQ) {
3124 if (tn_sopt(DO, opt) < 0)
3126 TELOPT_UNANSWERED_DO(opt) = 1;
3133 if (tn_wait("pre-encrypt") < 0) {
3140 #ifdef CK_ENCRYPTION
3141 if (tn_init) /* tn_ini() may be called recursively */
3144 if (!TELOPT_ME(TELOPT_ENCRYPTION) &&
3145 TELOPT_ME_MODE(TELOPT_ENCRYPTION) >= TN_NG_RQ) {
3146 if (tn_sopt(WILL, TELOPT_ENCRYPTION) < 0)
3148 TELOPT_UNANSWERED_WILL(TELOPT_ENCRYPTION) = 1;
3151 if (!TELOPT_U(TELOPT_ENCRYPTION) &&
3152 TELOPT_U_MODE(TELOPT_ENCRYPTION) >= TN_NG_RQ) {
3153 if (tn_sopt(DO, TELOPT_ENCRYPTION) < 0)
3155 TELOPT_UNANSWERED_DO(TELOPT_ENCRYPTION) = 1;
3159 /* If we are going to encrypt, we want to do it before we send any more */
3160 /* data, especially the terminal type and environment variables. */
3162 if (tn_wait("post-encrypt") < 0) {
3168 #endif /* CK_ENCRYPTION */
3172 if (tn_init) /* tn_ini() may be called recursively */
3176 /* Kermit Server negotiation must go last */
3177 /* Send U before ME */
3179 if (!TELOPT_U(TELOPT_KERMIT) &&
3180 TELOPT_U_MODE(TELOPT_KERMIT) >= TN_NG_RQ) {
3181 if (tn_sopt(DO, TELOPT_KERMIT) < 0)
3183 TELOPT_UNANSWERED_DO(TELOPT_KERMIT) = 1;
3186 if (!TELOPT_ME(TELOPT_KERMIT) &&
3187 TELOPT_ME_MODE(TELOPT_KERMIT) >= TN_NG_RQ) {
3188 if (tn_sopt(WILL, TELOPT_KERMIT) < 0)
3190 TELOPT_UNANSWERED_WILL(TELOPT_KERMIT) = 1;
3193 #endif /* IKS_OPTION */
3196 if (tn_wait("end of telnet negotiations") < 0) {
3203 tn_sdsb(); /* Send delayed subnegotiations */
3208 /* Start a telnet connection. */
3209 /* Returns -1 on error, 0 if nothing happens, 1 if init msgs sent ok */
3215 debug(F101,"tn_ini ttnproto","",ttnproto);
3216 debug(F101,"tn_ini tn_init","",tn_init);
3218 if (ttnet != NET_TCPB) /* Make sure connection is TCP/IP */
3220 if (tn_init) /* Have we done this already? */
3221 return(0); /* Don't do it again. */
3223 tn_reset(); /* Reset telnet parameters */
3224 tn_begun = 0; /* Reset; will be set by tn_start() */
3226 switch ( ttnproto ) {
3234 debug(F100,"tn_ini telnet negotiations ignored","tn_init",tn_init);
3238 case NP_TLS: /* If not talking to a telnet port, */
3239 ttnproto = NP_TELNET; /* pretend it's telnet anyway, */
3240 oldplex = duplex; /* save old duplex value */
3241 duplex = 1; /* and set to half duplex for telnet */
3243 debug(F100,"tn_ini skipping telnet negotiations","",0);
3245 tn_wait("tn_ini - waiting to see if telnet negotiations were sent");
3248 case NP_TCPRAW: /* Raw socket requested. */
3249 debug(F100,"tn_ini telnet negotiations ignored","tn_init",tn_init);
3251 case NP_KERMIT: /* switching to Telnet protocol */
3254 debug(F101,"tn_ini switching from XXX to Telnet","",ttnproto);
3255 ttnproto = NP_TELNET;
3258 /* We are already using a variation on Telnet protocol */
3263 tn_init = 1; /* Remember successful completion. */
3265 /* Don't send anything else! */
3266 debug(F101,"tn_ini duplex","",duplex);
3267 debug(F101,"tn_ini done, tn_init","",tn_init);
3273 tn_hex(CHAR * buf, int buflen, CHAR * data, int datalen)
3274 #else /* CK_ANSIC */
3275 tn_hex(buf, buflen, data, datalen)
3280 #endif /* CK_ANSIC */
3282 int i = 0, j = 0, k = 0;
3283 CHAR tmp[16]; /* in case value is treated as negative */
3287 for (k=0; k < datalen; k++) {
3288 if (data[k] < 32 || data[k] >= 127) {
3289 sprintf(tmp,"%s%02X ",was_hex?"":"\" ",data[k]);
3292 sprintf(tmp,"%s%c",was_hex?"\"":"",data[k]);
3295 ckstrncat((char *)buf,tmp,buflen);
3298 ckstrncat((char *)buf,"\" ",buflen);
3300 if (datalen <= 0 || data == NULL || buf == NULL || buflen <= 0)
3303 for (i = 0; i < datalen; i++) {
3304 ckstrncat((char *)buf,"\r\n ",buflen);
3305 for (j = 0 ; (j < 16); j++) {
3306 if ((i + j) < datalen)
3307 sprintf((char *)tmp,
3309 (j == 8 ? "| " : ""),
3310 (unsigned int) data[i + j]
3313 sprintf((char *)tmp,
3315 (j == 8 ? "| " : "")
3317 ckstrncat((char *)buf,(char *)tmp,buflen);
3319 ckstrncat((char *)buf," ",buflen);
3320 for (k = 0; (k < 16) && ((i + k) < datalen); k++) {
3321 sprintf((char *)tmp,
3323 (k == 8 ? " " : ""),
3324 isprint((char)(data[i+k])) ? data[i+k] : '.'
3326 ckstrncat((char *)buf,(char *)tmp,buflen);
3330 ckstrncat((char *)buf,"\r\n ",buflen);
3331 #endif /* COMMENT */
3332 return(strlen((char *)buf));
3336 tn_debug(s) char *s; {
3341 void cwrite(unsigned short);
3343 _PROTOTYP (void os2bold, (void));
3344 extern int tt_type_mode;
3347 if (!(tn_deb || debses))
3349 debug(F111,"tn_debug",s,what);
3352 extern unsigned char colorcmd;
3357 if (!scrninitialized[VTERM]) {
3361 SaveCmdMode(x+1,y+1);
3366 if ( ISVTNT(tt_type_mode) && ttnum != -1 && !debses )
3369 RequestVscrnMutex( VTERM, SEM_INDEFINITE_WAIT ) ;
3371 os2bold(); /* Toggle boldness */
3373 cwrite((CHAR) *p++); /* Go boldly ... */
3374 os2bold(); /* Toggle boldness back */
3377 cwrite((CHAR) '\015');
3378 cwrite((CHAR) '\012');
3381 cwrite((CHAR) '\015');
3382 cwrite((CHAR) '\012');
3384 ReleaseVscrnMutex(VTERM) ;
3386 if (what != W_CONNECT && what != W_DIALING &&
3387 what != W_COMMAND && what != W_NOTHING)
3388 return; /* CONNECT/command must be active */
3391 #endif /* NOLOCAL */
3395 Process in-band Telnet negotiation characters from the remote host.
3396 Call with the telnet IAC character and the current duplex setting
3397 (0 = remote echo, 1 = local echo), and a pointer to a function to call
3398 to read more characters. Returns:
3399 6 if DO LOGOUT was received and accepted
3400 5 if the Kermit start of packet character has changed
3401 4 if state of remote Internet Kermit Service has changed
3402 3 if a quoted IAC was received
3403 2 if local echo must be changed to remote
3404 1 if remote echo must be changed to local
3405 0 if nothing happens or no action necessary
3406 -1 on failure (= internal or i/o error)
3410 tn_siks(cmd) int cmd; { /* TELNET SEND IKS SUB */
3413 extern CHAR mystch; /* Outgoing Start of Packet Char */
3419 if (ttnet != NET_TCPB) return(0); /* Must be TCP/IP */
3420 if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
3421 if (cmd < KERMIT_START || cmd > KERMIT_RESP_STOP) /* Illegal subcommand */
3425 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
3429 if (cmd == KERMIT_START || cmd == KERMIT_RESP_START) {
3430 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
3431 } else if (cmd == KERMIT_STOP || cmd == KERMIT_RESP_STOP) {
3432 TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
3433 } else if (cmd == KERMIT_REQ_STOP)
3434 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 1;
3435 else if (cmd == KERMIT_REQ_START)
3436 TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 1;
3438 if (cmd == KERMIT_SOP) {
3439 buf[0] = (CHAR) IAC;
3441 buf[2] = (CHAR) TELOPT_KERMIT;
3442 buf[3] = (CHAR) (cmd & 0xff);
3443 buf[4] = (CHAR) mystch;
3444 buf[5] = (CHAR) IAC;
3448 if (tn_deb || debses || deblog)
3449 ckmakmsg( tn_msg_out,TN_MSG_LEN,"TELNET SENT SB KERMIT SOP ",
3450 ckctox(mystch,1)," IAC SE",NULL);
3453 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3456 debug(F101,tn_msg_out,"",cmd);
3457 if (tn_deb || debses) tn_debug(tn_msg_out);
3459 rc = ( ttol(buf,7) < 7 ); /* Send it. */
3461 ReleaseTelnetMutex();
3466 buf[0] = (CHAR) IAC;
3468 buf[2] = (CHAR) TELOPT_KERMIT;
3469 buf[3] = (CHAR) (cmd & 0xff);
3470 buf[4] = (CHAR) IAC;
3475 if (tn_deb || debses || deblog) {
3478 case KERMIT_START: s = "START"; break;
3479 case KERMIT_STOP: s = "STOP"; break;
3480 case KERMIT_REQ_START: s = "REQ-START"; break;
3481 case KERMIT_REQ_STOP: s = "REQ-STOP"; break;
3482 case KERMIT_RESP_START: s = "RESP-START"; break;
3483 case KERMIT_RESP_STOP: s = "RESP-STOP"; break;
3485 ckmakmsg( tn_msg_out,TN_MSG_LEN,
3486 "TELNET SENT SB kermit ",s," IAC SE",NULL);
3490 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3493 debug(F101,tn_msg_out,"",cmd);
3494 if (tn_deb || debses) tn_debug(tn_msg_out);
3496 rc = ( ttol(buf,6) < 6 ); /* Send it. */
3498 ReleaseTelnetMutex();
3505 #endif /* IKS_OPTION */
3507 /* tn_sb() performs Telnet Subnegotiation Parsing and Debugging */
3508 /* returns <= 0 on error, 1 on success */
3509 /* the length returned includes the IAC SE bytes */
3512 #ifdef CK_ANSIC /* TELNET SB */
3513 tn_sb( int opt, int * len, int (*fn)(int) )
3515 tn_sb( opt, len, fn ) int opt; int * len; int (*fn)();
3516 #endif /* CK_ANSIC */
3518 int c, x, y, n, m, flag;
3519 debug(F100,"Entering tn_sb()","",0);
3520 *len = 0; /* Initialize Len to 0 */
3521 n = flag = 0; /* Flag for when done reading SB */
3522 while (n < TSBUFSIZ) { /* Loop looking for IAC SE */
3523 if ((y = (*fn)(0)) < 0) /* Read a byte */
3525 y &= 0xff; /* Make sure it's just 8 bits. */
3526 sb[n++] = (char) y; /* Deposit in buffer. */
3527 if (seslog && sessft == XYFT_D) { /* Take care of session log */
3530 if (y == IAC) { /* If this is an IAC */
3531 if (flag) { /* If previous char was IAC */
3532 n--; /* it's quoted, keep one IAC */
3533 flag = 0; /* and turn off the flag. */
3534 } else flag = 1; /* Otherwise set the flag. */
3535 } else if (flag) { /* Something else following IAC */
3536 if (y == SE) /* If not SE, it's a protocol error */
3538 else if (y == DONT) { /* Used DONT instead of SE */
3540 "TELNET Subnegotiation error - used DONT instead of SE!",
3544 if (tn_deb || debses)
3546 "TELNET Subnegotiation error - used DONT instead of SE!");
3549 } else { /* Other protocol error */
3556 if ( opt == TELOPT_FORWARD_X && sb[0] == FWDX_DATA &&
3557 n >= (TSBUFSIZ-4) && !flag ) {
3558 /* do not let the buffer over flow */
3559 /* write the data to the channel and continue processing */
3560 /* the incoming data until IAC SE is reached. */
3565 if ( deblog || tn_deb || debses ) {
3567 ckmakmsg( tn_msg,TN_MSG_LEN,
3568 "TELNET RCVD SB ",TELOPT(opt),
3569 " DATA(buffer-full) ",NULL);
3570 tn_hex(tn_msg,TN_MSG_LEN,&sb[1],n-3);
3572 ckstrncat(tn_msg," SE",TN_MSG_LEN);
3574 ckstrncat(tn_msg," IAC DONT",TN_MSG_LEN);
3576 ckstrncat(tn_msg," IAC SE",TN_MSG_LEN);
3577 debug(F100,tn_msg,"",0);
3578 if (tn_deb || debses)
3583 if ( fwdx_tn_sb(sb,n) < 0 ) {
3584 debug(F100,"fxdx_tn_sb() failed","",0);
3585 /* We can't return though because that would leave */
3586 /* data to be forwarded in the queue to the be sent */
3587 /* to the terminal emulator. */
3589 /* reset leave the msg type and channel number in place */
3592 #endif /* CK_FORWARD_X */
3594 debug(F111,"tn_sb end of while loop","flag",flag);
3595 if (!flag) { /* Make sure we got a valid SB */
3596 debug(F111, "TELNET Subnegotiation prematurely broken","opt",opt);
3597 if (tn_deb || debses) {
3598 ckmakmsg( tn_msg, TN_MSG_LEN,
3599 "TELNET ", TELOPT(opt),
3600 " Subnegotiation prematurely broken",NULL
3605 /* Was -1 but that would be an I/O error, so absorb it and go on. */
3609 if (deblog || tn_deb || debses) {
3612 for (i = 0; i < 16; i++)
3614 if (opt == TELOPT_NAWS) {
3622 if (opt == TELOPT_FORWARD_X)
3624 else if (opt == TELOPT_KERMIT)
3626 else if (opt == TELOPT_LFLOW)
3628 else if (opt == TELOPT_COMPORT)
3632 if (opt == TELOPT_ENCRYPTION) {
3634 if (sb[1] < ENCTYPE_CNT) {
3635 s[1] = enctype_names[sb[1]];
3642 s[2] = "FB64_IV_OK";
3645 s[2] = "FB64_IV_BAD";
3648 s[2] = "FB64_CHALLENGE";
3651 s[2] = "FB64_RESPONSE";
3658 if (opt == TELOPT_AUTHENTICATION) {
3660 s[1] = AUTHTYPE_NAME(sb[1]);
3661 s[2] = AUTHMODE_NAME(sb[2]);
3680 s[3] = "NTLM_CHALLENGE";
3689 s[3] = "NTLM_RESPONSE";
3698 s[3] = "NTLM_ACCEPT";
3700 case 1: /* KERBEROS_v4 */
3704 case 2: /* KERBEROS_v5 */
3715 s[3] = "NTLM_REJECT";
3717 case 1: /* KERBEROS_V4 */
3721 case 2: /* KERBEROS_V5 */
3731 case 2: /* KERBEROS_V5 */
3732 s[3] = "FORWARD_ACCEPT";
3739 s[3] = "FORWARD_ACCEPT";
3741 case 2: /* KERBEROS_V5 */
3742 s[3] = "FORWARD_REJECT";
3749 s[3] = "FORWARD_REJECT";
3751 case 2: /* KERBEROS_V5 */
3752 s[3] = "TLS_VERIFY";
3776 case TELOPT_FORWARD_X:
3785 case TELOPT_COMPORT:
3786 s[0] = "SET-BAUDRATE";
3788 case TELOPT_AUTHENTICATION:
3791 for (; i < n-2; i += 2) {
3792 if ( AUTHTYPE_NAME_OK(sb[i]) &&
3793 AUTHMODE_NAME_OK(sb[i]))
3794 ckmakmsg( tn_msg, TN_MSG_LEN,
3795 AUTHTYPE_NAME(sb[i])," ",
3796 AUTHMODE_NAME(sb[i+1])," "
3799 ckmakxmsg(tn_msg, TN_MSG_LEN,
3800 AUTHTYPE_NAME(sb[i]),
3804 AUTHMODE_NAME(sb[i+1]),
3810 ckstrncat(hexbuf,tn_msg,sizeof(hexbuf));
3815 case TELOPT_ENCRYPTION:
3818 s[i] = enctype_names[sb[i]];
3823 case TELOPT_START_TLS:
3833 case TELOPT_FORWARD_X:
3837 s[0] = "RESTART-ANY";
3842 case TELOPT_COMPORT:
3843 s[0] = "SET-DATASIZE";
3845 case TELOPT_NEWENVIRON:
3848 case TELOPT_AUTHENTICATION:
3851 s[1] = AUTHTYPE_NAME(sb[1]);
3852 s[2] = AUTHMODE_NAME(sb[2]);
3866 s[3] = "NTLM_CHALLENGE";
3875 s[3] = "NTLM_RESPONSE";
3884 s[3] = "NTLM_ACCEPT";
3886 case AUTHTYPE_KERBEROS_V4:
3890 case AUTHTYPE_KERBEROS_V5:
3898 s[3] = "NTLM_REJECT";
3900 case AUTHTYPE_KERBEROS_V4:
3904 case AUTHTYPE_KERBEROS_V5:
3914 case AUTHTYPE_KERBEROS_V5:
3915 s[3] = "FORWARD_ACCEPT";
3922 s[3] = "FORWARD_ACCEPT";
3924 case AUTHTYPE_KERBEROS_V5:
3925 s[3] = "FORWARD_REJECT";
3932 s[3] = "FORWARD_REJECT";
3934 case AUTHTYPE_KERBEROS_V5:
3935 s[3] = "TLS_VERIFY";
3955 case TELOPT_ENCRYPTION:
3957 s[1] = enctype_names[sb[1]];
3966 s[2] = "FB64_IV_OK";
3970 s[2] = "FB64_IV_BAD";
3974 s[2] = "FB64_CHALLENGE";
3978 s[2] = "FB64_RESPONSE";
3986 case TELOPT_FORWARD_X:
3990 s[0] = "RESTART-XON";
3995 case TELOPT_COMPORT:
3996 s[0] = "SET-PARITY";
3998 case TELOPT_AUTHENTICATION:
4001 case TELOPT_ENCRYPTION:
4008 case TELOPT_FORWARD_X:
4014 case TELOPT_COMPORT:
4015 s[0] = "SET-STOPSIZE";
4017 case TELOPT_ENCRYPTION:
4024 case TELOPT_FORWARD_X:
4025 s[0] = "OPTION_DATA";
4027 case TELOPT_ENCRYPTION:
4028 s[0] = "REQUEST-START";
4030 case TELOPT_COMPORT:
4031 s[0] = "SET-CONTROL";
4037 case TELOPT_FORWARD_X:
4040 case TELOPT_ENCRYPTION:
4041 s[0] = "REQUEST-END";
4043 case TELOPT_COMPORT:
4044 s[0] = "NOTIFY-LINESTATE";
4050 case TELOPT_FORWARD_X:
4053 case TELOPT_ENCRYPTION:
4056 case TELOPT_COMPORT:
4057 s[0] = "NOTIFY-MODEMSTATE";
4064 s[0] = "RESP-START";
4066 case TELOPT_ENCRYPTION:
4069 case TELOPT_COMPORT:
4070 s[0] = "FLOWCONTROL-SUSPEND";
4079 case TELOPT_COMPORT:
4080 s[0] = "FLOWCONTROL-RESUME";
4086 case TELOPT_COMPORT:
4087 s[0] = "SET-LINESTATE-MASK";
4093 case TELOPT_COMPORT:
4094 s[0] = "SET-MODEMSTATE-MASK";
4100 case TELOPT_COMPORT:
4101 s[0] = "PURGE-DATA";
4109 case TELOPT_COMPORT:
4110 s[0] = "S_SIGNATURE";
4116 case TELOPT_COMPORT:
4117 s[0] = "S_SET-BAUDRATE";
4123 case TELOPT_COMPORT:
4124 s[0] = "S_SET-DATASIZE";
4130 case TELOPT_COMPORT:
4131 s[0] = "S_SET-PARITY";
4137 case TELOPT_COMPORT:
4138 s[0] = "S_SET-STOPSIZE";
4144 case TELOPT_COMPORT:
4145 s[0] = "S_SET-CONTROL";
4151 case TELOPT_COMPORT:
4152 s[0] = "S_NOTIFY-LINESTATE";
4158 case TELOPT_COMPORT:
4159 s[0] = "S_NOTIFY-MODEMSTATE";
4165 case TELOPT_COMPORT:
4166 s[0] = "S_FLOWCONTROL-SUSPEND";
4172 case TELOPT_COMPORT:
4173 s[0] = "S_FLOWCONTROL-RESUME";
4179 case TELOPT_COMPORT:
4180 s[0] = "S_SET-LINESTATE-MASK";
4186 case TELOPT_COMPORT:
4187 s[0] = "S_SET-MODEMSTATE-MASK";
4193 case TELOPT_COMPORT:
4194 s[0] = "S_PURGE-DATA";
4202 int len, param, param_len;
4203 ckmakmsg( tn_msg, TN_MSG_LEN,
4205 TELOPT(opt)," ",NULL);
4206 len = strlen(tn_msg);
4207 for (param = 0; param <= 15; param++) {
4208 param_len = strlen(s[param]);
4209 if (param_len > 0) {
4210 strcpy(&tn_msg[len], s[param]);
4212 tn_msg[len++] = ' ';
4218 ckmakxmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD SB ",TELOPT(opt)," ",
4219 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
4222 for (i = 0; i < 16; i++) {
4224 ckstrncat(tn_msg,s[i],TN_MSG_LEN);
4225 ckstrncat(tn_msg," ",TN_MSG_LEN);
4229 #endif /* M_XENIX */
4230 tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&sb[i],n-2-i);
4232 ckstrncat(tn_msg," SE",TN_MSG_LEN);
4234 ckstrncat(tn_msg," IAC DONT",TN_MSG_LEN);
4236 ckstrncat(tn_msg," IAC SE",TN_MSG_LEN);
4237 debug(F100,tn_msg,"",0);
4238 if (tn_deb || debses)
4241 debug(F111,"tn_sb","len",n);
4243 *len = n; /* return length */
4244 return(1); /* success */
4247 static char rows_buf[16] = { 0, 0 }; /* LINES Environment variable */
4248 static char cols_buf[16] = { 0, 0 }; /* COLUMNS Enviornment variable */
4249 static char term_buf[64] = { 0, 0 }; /* TERM Environment variable */
4254 _PROTOTYP(int tgetent,(char *, char *));
4255 #endif /* COHERENT */
4258 _PROTOTYP(int tgetent,(char *, char *));
4261 extern char * trmbuf; /* Real curses */
4262 #endif /* CK_CURSES */
4264 #ifdef CK_ENCRYPTION
4268 /* Prevent Encryption from being negotiated */
4269 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
4270 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
4272 /* Cancel any negotiation that might have started */
4275 if (TELOPT_ME(TELOPT_ENCRYPTION) ||
4276 TELOPT_UNANSWERED_WILL(TELOPT_ENCRYPTION)) {
4277 TELOPT_ME(TELOPT_ENCRYPTION) = 0;
4278 if (tn_sopt(WONT,TELOPT_ENCRYPTION) < 0)
4280 TELOPT_UNANSWERED_WONT(TELOPT_ENCRYPTION) = 1;
4282 if (TELOPT_U(TELOPT_ENCRYPTION) ||
4283 TELOPT_UNANSWERED_DO(TELOPT_ENCRYPTION)) {
4284 TELOPT_U(TELOPT_ENCRYPTION) = 0;
4285 if (tn_sopt(DONT,TELOPT_ENCRYPTION) < 0)
4287 TELOPT_UNANSWERED_DONT(TELOPT_ENCRYPTION) = 1;
4291 #endif /* CK_ENCRYPTION */
4293 /* The following note came from the old SGA negotiation code. This should */
4294 /* no longer be necessary with the New Telnet negotiation state machine. */
4296 Note: The following is proper behavior, and required for talking to the
4297 Apertus interface to the NOTIS library system, e.g. at Iowa State U:
4298 scholar.iastate.edu. Without this reply, the server hangs forever. This
4299 code should not be loop-inducing, since C-Kermit never sends WILL SGA as
4300 an initial bid, so if DO SGA comes, it is never an ACK.
4304 -1 = Telnet Option negotiation error
4305 -2 = Connection closed by peer
4306 -3 = Connection closed by us
4317 #ifdef CK_ANSIC /* TELNET DO OPTION */
4318 tn_xdoop(CHAR z, int echo, int (*fn)(int))
4320 tn_xdoop(z, echo, fn) CHAR z; int echo; int (*fn)();
4321 #endif /* CK_ANSIC */
4328 int inautodl = 0, cmdadl = 1;
4331 extern int autodl, inautodl, cmdadl;
4332 #endif /* CK_AUTODL */
4334 #endif /* IKS_OPTION */
4337 /* Have IAC, read command character. */
4339 while ((c = (*fn)(0)) == -1); /* Read command character */
4342 c &= 0xFF; /* Strip high bits */
4344 if (!TELCMD_OK(c)) {
4346 if (tn_deb || debses || deblog) {
4347 ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD UNKNOWN (",
4348 ckitoa(c),")",NULL);
4349 debug(F101,tn_msg,"",c);
4350 if (tn_deb || debses)
4356 if (ttnproto == NP_NONE) {
4357 debug(F100,"tn_doop discovered a Telnet command",
4358 "ttnproto = NP_TELNET",0);
4359 ttnproto = NP_TELNET;
4361 if (seslog && sessft == XYFT_D) { /* Copy to session log, if any. */
4366 if (c == (CHAR) IAC) /* Quoted IAC */
4369 if (c < SB) { /* Other command with no arguments. */
4371 if (deblog || tn_deb || debses) {
4372 ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD ",TELCMD(c),NULL,NULL);
4373 debug(F101,tn_msg,"",c);
4374 if (tn_deb || debses) tn_debug(tn_msg);
4377 switch (c) { /* What we would like to do here */
4378 case TN_GA: /* Is substitute ASCII characters */
4379 break; /* for the Telnet Command so that */
4380 case TN_EL: /* the command may be processed by */
4381 break; /* either the internal emulator or */
4382 case TN_EC: /* by the superior process or shell */
4386 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
4388 ttol((CHAR *)"[Yes]\015\012",7);
4390 ReleaseTelnetMutex();
4396 #endif /* BETADEBUG */
4422 /* SB, WILL, WONT, DO, or DONT need more bytes... */
4424 if ((x = (*fn)(0)) < 0) /* Get the option. */
4426 x &= 0xff; /* Trim to 8 bits. */
4428 if (seslog && sessft == XYFT_D) { /* Session log */
4432 if ((deblog || tn_deb || debses) && c != SB) {
4433 ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD ",TELCMD(c)," ",TELOPT(x));
4434 debug(F101,tn_msg,"",x);
4435 if (tn_deb || debses) tn_debug(tn_msg);
4438 /* Now handle the command */
4442 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
4446 if (x == TELOPT_FORWARD_X) {
4447 if (!fwdx_server_avail() || !(fwdx_no_encrypt ||
4449 (ssl_active_flag || tls_active_flag)
4454 #ifdef CK_ENCRYPTION
4455 (ck_tn_encrypting() && ck_tn_decrypting())
4456 #else /* CK_ENCRYPTION */
4458 #endif /* CK_ENCRYPTION */
4460 TELOPT_U_MODE(TELOPT_FORWARD_X) = TN_NG_RF;
4461 TELOPT_ME_MODE(TELOPT_FORWARD_X) = TN_NG_RF;
4464 #endif /* CK_FORWARD_X */
4465 if (!TELOPT_OK(x) || TELOPT_U_MODE(x) == TN_NG_RF) {
4466 if (tn_sopt(DONT,x) < 0)
4468 if (TELOPT_UNANSWERED_DO(x))
4469 TELOPT_UNANSWERED_DO(x) = 0;
4470 } else if (!TELOPT_U(x)) {
4471 if (!TELOPT_UNANSWERED_DO(x)) {
4472 if (tn_sopt(DO,x) < 0)
4475 if (TELOPT_UNANSWERED_DO(x))
4476 TELOPT_UNANSWERED_DO(x) = 0;
4481 case TELOPT_START_TLS:
4483 If my proposal is accepted, at this point the Telnet
4484 protocol is turned off and a TLS negotiation takes
4487 Start by sending SB START_TLS FOLLOWS to signal
4488 we are ready. Wait for the peer to send the same
4489 and then start the TLS negotiation.
4491 If the TLS negotiation succeeds we call tn_ini()
4492 again to reset the telnet state machine and restart
4493 the negotiation process over the now secure link.
4495 If the TLS negotiation fails, we call ttclos()
4496 to terminate the connection.
4498 Only the server should receive a WILL START_TLS
4500 tn_ssbopt(TELOPT_START_TLS,1,NULL,0);
4501 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 1;
4505 #ifdef CK_AUTHENTICATION
4506 case TELOPT_AUTHENTICATION: {
4507 /* We now have to perform a SB SEND to identify the */
4508 /* supported authentication types to the other side. */
4509 extern int authentication_version;
4512 /* if we have an outstanding DO START_TLS then we must
4513 * wait for the response before we determine what to do
4515 if (TELOPT_UNANSWERED_DO(TELOPT_START_TLS)) {
4516 TELOPT_SB(TELOPT_START_TLS).start_tls.auth_request = 1;
4520 authentication_version = AUTHTYPE_AUTO;
4521 ck_tn_auth_request();
4524 #endif /* CK_AUTHENTICATION */
4525 #ifdef CK_ENCRYPTION
4526 case TELOPT_ENCRYPTION:
4527 if (!(TELOPT_ME(TELOPT_AUTHENTICATION) ||
4528 TELOPT_U(TELOPT_AUTHENTICATION))
4530 if (tn_sopt(DONT,x) < 0)
4534 if (ck_tn_auth_in_progress()) {
4535 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 1;
4537 /* Perform subnegotiation */
4538 ck_encrypt_send_support();
4540 if (!(TELOPT_ME(x) || TELOPT_UNANSWERED_WILL(x))
4541 && TELOPT_ME_MODE(x) != TN_NG_RF) {
4542 if (tn_sopt(WILL, x) < 0)
4544 TELOPT_UNANSWERED_WILL(x) = 1;
4548 #endif /* CK_ENCRYPTION */
4551 if (!TELOPT_ME(x)) {
4552 /* Tell the other side what Start of Packet Character */
4553 tn_siks(KERMIT_SOP); /* SOP */
4555 if (!TELOPT_UNANSWERED_WILL(x) &&
4556 TELOPT_ME_MODE(x) != TN_NG_RF) {
4557 if (tn_sopt(WILL, x) < 0)
4559 TELOPT_UNANSWERED_WILL(x) = 1;
4563 #endif /* IKS_OPTION */
4565 if (!TELOPT_ME(x)) {
4566 if (!TELOPT_UNANSWERED_WILL(x) &&
4567 TELOPT_ME_MODE(x) >= TN_NG_RQ) {
4568 if (tn_sopt(WILL, x) < 0)
4570 TELOPT_UNANSWERED_WILL(x) = 1;
4576 if (TELOPT_UNANSWERED_DO(x))
4577 TELOPT_UNANSWERED_DO(x) = 0;
4583 tn_ssbopt(TELOPT_TTYPE,TELQUAL_SEND,NULL,0);
4584 TELOPT_UNANSWERED_SB(TELOPT_TTYPE)=1;
4586 #ifdef CK_ENVIRONMENT
4587 case TELOPT_NEWENVIRON: /* SB NEW-ENVIRON SEND */
4589 char request[6]; /* request it */
4590 sprintf(request,"%cUSER",TEL_ENV_VAR); /* safe */
4591 tn_ssbopt(TELOPT_NEWENVIRON,TELQUAL_SEND,request,
4593 TELOPT_UNANSWERED_SB(TELOPT_NEWENVIRON)=1;
4596 #endif /* CK_ENVIRONMENT */
4599 if (TELOPT_UNANSWERED_DO(x))
4600 TELOPT_UNANSWERED_DO(x) = 0;
4605 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
4608 if (TELOPT_U(x) || TELOPT_UNANSWERED_DO(x)) {
4609 /* David Borman says we should not respond DONT when
4610 * the WONT is a response to a DO that we sent.
4611 * Nor should we send one if the state is already WONT
4612 * such as when we do not recognize the option since
4613 * options are initialized in the WONT/DONT state.
4615 if (!(TELOPT_UNANSWERED_DO(x) || TELOPT_UNANSWERED_DONT(x)))
4616 if (tn_sopt(DONT,x) < 0)
4618 if (TELOPT_UNANSWERED_DONT(x))
4619 TELOPT_UNANSWERED_DONT(x) = 0;
4620 if (TELOPT_UNANSWERED_DO(x))
4621 TELOPT_UNANSWERED_DO(x) = 0;
4627 case TELOPT_START_TLS:
4629 if (TELOPT_U_MODE(x) == TN_NG_MU) {
4630 printf("Telnet Start-TLS refused.\n");
4632 whyclosed = WC_TELOPT;
4635 if (TELOPT_SB(x).start_tls.auth_request) {
4636 extern int authentication_version;
4637 TELOPT_SB(x).start_tls.auth_request = 0;
4638 authentication_version = AUTHTYPE_AUTO;
4639 ck_tn_auth_request();
4644 #ifdef CK_AUTHENTICATION
4645 case TELOPT_AUTHENTICATION:
4646 if (sstelnet && TELOPT_U_MODE(x) == TN_NG_MU) {
4647 printf("Telnet authentication refused.\n");
4649 whyclosed = WC_TELOPT;
4651 } else if (TELOPT_U_MODE(x) == TN_NG_RQ) {
4652 TELOPT_U_MODE(x) = TN_NG_AC;
4654 if (ck_tn_auth_in_progress())
4655 printf("Telnet authentication refused.\n");
4656 #ifdef CK_ENCRYPTION
4658 if (tn_no_encrypt()<0)
4661 #endif /* CK_ENCRYPTION */
4663 #endif /* CK_AUTHENTICATION */
4664 #ifdef CK_ENCRYPTION
4665 case TELOPT_ENCRYPTION:
4668 #endif /* CK_ENCRYPTION */
4671 TELOPT_SB(x).kermit.u_start = 0;
4672 TELOPT_SB(x).kermit.me_req_start = 0;
4673 TELOPT_SB(x).kermit.me_req_stop = 0;
4675 #endif /* IKS_OPTION */
4677 /* The client does not support NAWS. */
4678 /* Assume a height of 24 and a width of 80 */
4690 VscrnSetWidth(VTERM, w);
4691 VscrnSetHeight(VTERM, h+(tt_status[VTERM]?1:0));
4700 VscrnSetWidth(VCMD, w);
4701 VscrnSetHeight(VCMD, h);
4709 #endif /* NOLOCAL */
4710 /* Add LINES and COLUMNS to the environment */
4711 ckmakmsg((char *)rows_buf,16,"LINES=",ckitoa(h),
4713 ckmakmsg((char *)cols_buf,16,"COLUMNS=",ckitoa(w),
4719 #endif /* NOPUTENV */
4720 #endif /* OS2ORUNIX */
4726 if (TELOPT_UNANSWERED_DO(x))
4727 TELOPT_UNANSWERED_DO(x) = 0;
4733 if (TELOPT_UNANSWERED_DONT(x))
4734 TELOPT_UNANSWERED_DONT(x) = 0;
4735 if (TELOPT_UNANSWERED_DO(x))
4736 TELOPT_UNANSWERED_DO(x) = 0;
4738 if (TELOPT_U_MODE(x) == TN_NG_MU) {
4739 ckmakmsg( tn_msg,TN_MSG_LEN,
4740 "Peer refuses TELNET DO ",TELOPT(x),
4741 " negotiations - terminating connection",NULL
4743 debug(F100,tn_msg,"",0);
4744 if (tn_deb || debses) tn_debug(tn_msg);
4745 printf("%s\n",tn_msg);
4747 whyclosed = WC_TELOPT;
4751 if (x == TELOPT_ECHO && !echo) /* Special handling for echo */
4752 return(1); /* because we allow 'duplex' */
4753 #endif /* COMMENT */
4758 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
4761 if (!TELOPT_OK(x) || TELOPT_ME_MODE(x) == TN_NG_RF) {
4762 if (tn_sopt(WONT,x) < 0)
4764 if (TELOPT_UNANSWERED_WILL(x))
4765 TELOPT_UNANSWERED_WILL(x) = 0;
4766 } else if (!TELOPT_ME(x)) {
4767 if (!TELOPT_UNANSWERED_WILL(x)) {
4768 if (tn_sopt(WILL,x) < 0)
4771 if (TELOPT_UNANSWERED_WILL(x))
4772 TELOPT_UNANSWERED_WILL(x) = 0;
4777 case TELOPT_START_TLS:
4779 If my proposal is accepted at this point the Telnet
4780 protocol is turned off and a TLS negotiation takes
4783 Start by sending SB START_TLS FOLLOWS to signal
4784 we are ready. Wait for the peer to send the same
4785 and then start the TLS negotiation.
4787 If the TLS negotiation succeeds we call tn_ini()
4788 again to reset the telnet state machine and restart
4789 the negotiation process over the now secure link.
4791 If the TLS negotiation fails, we call ttclos()
4792 to terminate the connection. Then we set the
4793 U_MODE and ME_MODE for TELOPT_START_TLS to REFUSE
4794 and then call ttopen() to create a new connection
4795 to the same host but this time do not attempt
4798 Only the client should receive DO START_TLS.
4800 tn_ssbopt(TELOPT_START_TLS,1,NULL,0);
4801 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 1;
4805 #ifdef CK_AUTHENTICATION
4806 case TELOPT_AUTHENTICATION: {
4807 /* We don't know what authentication we are using yet */
4808 /* but it is not NULL until a failure is detected so */
4809 /* use AUTO in the meantime. */
4810 extern int authentication_version;
4811 authentication_version = AUTHTYPE_AUTO;
4814 #endif /* CK_AUTHENTICATION */
4815 #ifdef CK_ENCRYPTION
4816 case TELOPT_ENCRYPTION:
4817 if (!(TELOPT_ME(TELOPT_AUTHENTICATION) ||
4818 TELOPT_U(TELOPT_AUTHENTICATION))
4820 if (tn_sopt(WONT,x) < 0)
4824 if (!(TELOPT_U(x) || TELOPT_UNANSWERED_DO(x))
4825 && TELOPT_U_MODE(x) != TN_NG_RF) {
4826 if (tn_sopt(DO, x) < 0)
4828 TELOPT_UNANSWERED_DO(x) = 1;
4832 #endif /* CK_ENCRYPTION */
4835 /* If currently processing Kermit server packets, must tell the other side */
4837 debug(F111,"tn_doop","what",what);
4838 debug(F111,"tn_doop","server",server);
4840 debug(F111,"tn_doop","autodl",autodl);
4841 debug(F111,"tn_doop","inautodl",inautodl);
4842 debug(F111,"tn_doop","cmdadl",cmdadl);
4843 #endif /* CK_AUTODL */
4847 || (local && ((what == W_CONNECT && autodl) ||
4848 (what != W_CONNECT && inautodl)))
4849 || (!local && cmdadl)
4850 #endif /* CK_AUTODL */
4852 tn_siks(KERMIT_START); /* START */
4855 /* Tell the other side what Start of Packet Character */
4856 tn_siks(KERMIT_SOP); /* SOP */
4857 if (!TELOPT_UNANSWERED_DO(x) &&
4858 TELOPT_U_MODE(x) != TN_NG_RF) {
4859 if (tn_sopt(DO, x) < 0)
4861 TELOPT_UNANSWERED_DO(x) = 1;
4865 #endif /* IKS_OPTION */
4869 if (!TELOPT_UNANSWERED_DO(x) &&
4870 TELOPT_U_MODE(x) >= TN_NG_RQ) {
4871 if (tn_sopt(DO, x) < 0)
4873 TELOPT_UNANSWERED_DO(x) = 1;
4879 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
4883 TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 1;
4885 #endif /* CK_NAWS */
4888 ttclos(0); /* And then hangup */
4889 whyclosed = WC_TELOPT;
4893 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
4894 if (tn_sndloc() < 0)
4897 TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 1;
4900 #endif /* CK_SNDLOC */
4902 case TELOPT_FORWARD_X:
4903 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
4904 if (fwdx_send_options() < 0) {
4905 if (tn_sopt(DONT,x) < 0)
4907 TELOPT_UNANSWERED_DONT(x) = 1;
4910 TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 1;
4913 #endif /* CK_FORWARD_X */
4915 case TELOPT_COMPORT: {
4916 extern int reliable;
4917 if (!tn_delay_sb || !tn_outst(0) || tn_init) {
4918 if (tn_sndcomport() < 0)
4921 TELOPT_SB(TELOPT_COMPORT).comport.need_to_send = 1;
4923 /* Telnet -> Serial -> ??? is not a reliable connection. */
4927 #endif /* TN_COMPORT */
4930 if (TELOPT_UNANSWERED_WILL(x))
4931 TELOPT_UNANSWERED_WILL(x) = 0;
4937 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
4940 if (TELOPT_ME(x) || TELOPT_UNANSWERED_WILL(x)) {
4941 /* David Borman says we should not respond WONT when
4942 * the DONT is a response to a WILL that we sent.
4943 * Nor should we send one if the state is already WONT
4944 * such as when we do not recognize the option since
4945 * options are initialized in the WONT/DONT state.
4947 if (!(TELOPT_UNANSWERED_WILL(x) || TELOPT_UNANSWERED_WONT(x)))
4948 if (tn_sopt(WONT,x) < 0)
4951 if (TELOPT_UNANSWERED_WILL(x))
4952 TELOPT_UNANSWERED_WILL(x) = 0;
4953 if (TELOPT_UNANSWERED_WONT(x))
4954 TELOPT_UNANSWERED_WONT(x) = 0;
4960 case TELOPT_START_TLS:
4961 if (!sstelnet && TELOPT_ME_MODE(x) == TN_NG_MU) {
4962 printf("Telnet Start-TLS refused.\n");
4964 whyclosed = WC_TELOPT;
4969 #ifdef CK_AUTHENTICATION
4970 case TELOPT_AUTHENTICATION:
4971 if (!sstelnet && TELOPT_ME_MODE(x) == TN_NG_MU) {
4973 if (tls_active_flag) {
4974 TELOPT_ME_MODE(x) = TN_NG_AC;
4979 printf("Telnet authentication refused.\n");
4981 whyclosed = WC_TELOPT;
4984 } else if (TELOPT_ME_MODE(x) == TN_NG_RQ) {
4985 TELOPT_ME_MODE(x) = TN_NG_AC;
4987 if (ck_tn_auth_in_progress())
4988 printf("Telnet authentication refused.\n");
4989 #ifdef CK_ENCRYPTION
4991 if (tn_no_encrypt()<0)
4994 #endif /* CK_ENCRYPTION */
4996 #endif /* CK_AUTHENTICATION */
4997 case TELOPT_ENCRYPTION:
4998 #ifdef CK_ENCRYPTION
5000 #endif /* CK_ENCRYPTION */
5004 TELOPT_SB(x).kermit.me_start = 0;
5005 #endif /* IKS_OPTION */
5011 if (TELOPT_UNANSWERED_WILL(x))
5012 TELOPT_UNANSWERED_WILL(x) = 0;
5013 if (TELOPT_UNANSWERED_WONT(x))
5014 TELOPT_UNANSWERED_WONT(x) = 0;
5016 if (TELOPT_ME_MODE(x) == TN_NG_MU) {
5017 ckmakmsg( tn_msg,TN_MSG_LEN,
5018 "Peer refuses TELNET WILL ",TELOPT(x),
5019 " negotiations - terminating connection",
5022 debug(F100,tn_msg,"",0);
5023 if (tn_deb || debses) tn_debug(tn_msg);
5024 printf("%s\n",tn_msg);
5026 whyclosed = WC_TELOPT;
5031 if ((y = tn_sb(x,&n,fn)) <= 0)
5035 /* Do not process subnegotiations other than START_TLS after we */
5036 /* have agreed to begin the TLS negotiation sequence. */
5037 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows &&
5038 x != TELOPT_START_TLS)
5042 if (!TELOPT_OK(x)) {
5043 hexdump("unknown telnet subnegotiation",sb,n);
5045 } else if ( !(TELOPT_ME(x) || TELOPT_U(x)) ) {
5046 hexdump("telnet option not negotiated",sb,n);
5049 if (TELOPT_UNANSWERED_WILL(x)) {
5050 TELOPT_UNANSWERED_WILL(x) = 0;
5052 ckmakmsg(tn_msg,TN_MSG_LEN,
5053 "TELNET DO ",TELOPT(x),
5054 "(implied by receipt of SB - protocol error ignored)",
5057 debug(F100,tn_msg,"",0);
5058 if (tn_deb || debses) tn_debug(tn_msg);
5060 if (TELOPT_UNANSWERED_DO(x)) {
5061 TELOPT_UNANSWERED_DO(x) = 0;
5063 ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET WILL ",TELOPT(x),
5064 " (implied by receipt of SB - protocol error ignored)",
5066 debug(F100,tn_msg,"",0);
5067 if (tn_deb || debses) tn_debug(tn_msg);
5071 TELOPT_UNANSWERED_SB(x)=0;
5074 case TELOPT_FORWARD_X:
5075 return(fwdx_tn_sb(sb, n));
5076 #endif /* CK_FORWARD_X */
5078 case TELOPT_START_TLS: {
5080 the other side is saying SB START_TLS FOLLOWS
5081 the incoming channel is now ready for starting the
5084 int def_tls_u_mode, def_tls_me_mode;
5085 int def_enc_u_mode, def_enc_me_mode;
5092 TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 1;
5093 /* Preserve the default modes and make sure we will */
5094 /* refuse START_TLS when we retry. */
5096 def_tls_u_mode = TELOPT_DEF_S_U_MODE(TELOPT_START_TLS);
5097 def_tls_me_mode = TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS);
5098 TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
5099 TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS)= TN_NG_RF;
5100 #ifdef CK_ENCRYPTION
5101 def_enc_u_mode = TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION);
5102 def_enc_me_mode = TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION);
5103 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
5104 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION)= TN_NG_RF;
5105 #endif /* CK_ENCRYPTION */
5107 def_tls_u_mode = TELOPT_DEF_C_U_MODE(TELOPT_START_TLS);
5108 def_tls_me_mode = TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS);
5109 TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
5110 TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS)= TN_NG_RF;
5111 #ifdef CK_ENCRYPTION
5112 def_enc_u_mode = TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION);
5113 def_enc_me_mode = TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION);
5114 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
5115 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION)= TN_NG_RF;
5116 #endif /* CK_ENCRYPTION */
5122 if (ck_tn_tls_negotiate()<0) {
5123 /* we failed. disconnect and if we are the client */
5124 /* then reconnect and try without START_TLS. */
5130 printf("TLS failed: Disconnecting.\n");
5131 TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = def_tls_u_mode;
5132 TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = def_tls_me_mode;
5133 #ifdef CK_ENCRYPTION
5134 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = def_enc_u_mode;
5135 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
5136 #endif /* CK_ENCRYPTION */
5138 whyclosed = WC_TELOPT;
5139 ttnproto = NP_TELNET;
5143 extern tls_norestore;
5144 #endif /* NOLOCAL */
5145 printf("TLS failed: Disconnecting...\n");
5146 #ifdef CK_ENCRYPTION
5147 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = def_enc_u_mode;
5148 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
5149 #endif /* CK_ENCRYPTION */
5150 /* if START_TLS is not REQUIRED, then retry without it */
5151 if ( def_tls_me_mode != TN_NG_MU ) {
5152 extern char ttname[];
5155 #endif /* NOLOCAL */
5157 whyclosed = WC_TELOPT;
5160 #endif /* NOLOCAL */
5161 ttnproto = NP_TELNET;
5162 printf("Reconnecting without TLS.\n");
5164 if (ttopen(ttname,&x,mdmtyp,0)<0)
5167 TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) =
5169 TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) =
5172 whyclosed = WC_TELOPT;
5173 ttnproto = NP_TELNET;
5178 #ifdef CK_AUTHENTICATION
5179 /* we succeeded. restart telnet negotiations from */
5180 /* the beginning. However, if we have received a */
5181 /* client certificate and we are a server, then do */
5182 /* not offer TELOPT_AUTH. */
5183 if ( ck_tn_auth_valid() == AUTH_VALID ) {
5184 TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_AC;
5185 TELOPT_DEF_S_ME_MODE(TELOPT_AUTHENTICATION)= TN_NG_AC;
5187 #endif /* CK_AUTHENTICATION */
5188 ttnproto = NP_TELNET;
5193 /* Restore the default modes */
5195 TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = def_tls_u_mode;
5196 TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = def_tls_me_mode;
5197 #ifdef CK_ENCRYPTION
5198 TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = def_enc_u_mode;
5199 TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
5200 #endif /* CK_ENCRYPTION */
5202 TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = def_tls_u_mode;
5203 TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = def_tls_me_mode;
5204 #ifdef CK_ENCRYPTION
5205 TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = def_enc_u_mode;
5206 TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
5207 #endif /* CK_ENCRYPTION */
5212 #ifdef CK_AUTHENTICATION
5213 case TELOPT_AUTHENTICATION:
5214 if (ck_tn_sb_auth((char *)sb,n) < 0) {
5215 if (sstelnet && TELOPT_U_MODE(x) == TN_NG_MU) {
5217 whyclosed = WC_TELOPT;
5219 } else if (!sstelnet && TELOPT_ME_MODE(x) == TN_NG_MU) {
5221 whyclosed = WC_TELOPT;
5224 if (TELOPT_ME_MODE(x) == TN_NG_RQ)
5225 TELOPT_ME_MODE(x) = TN_NG_AC;
5226 if (TELOPT_U_MODE(x) == TN_NG_RQ)
5227 TELOPT_U_MODE(x) = TN_NG_AC;
5231 if (tn_sopt(WONT,x) < 0)
5236 if (tn_sopt(DONT,x) < 0)
5239 #ifdef CK_ENCRYPTION
5240 if (tn_no_encrypt()<0)
5242 #endif /* CK_ENCRYPTION */
5244 #ifdef CK_ENCRYPTION
5245 if (!ck_tn_auth_in_progress()) { /* we are finished */
5246 if (ck_tn_authenticated() == AUTHTYPE_SSL) {
5247 /* TLS was successful. Disable ENCRYPTION */
5248 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
5249 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
5251 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send) {
5252 ck_encrypt_send_support();
5253 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 0;
5256 #endif /* CK_ENCRYPTION */
5259 #endif /* CK_AUTHENTICATION */
5260 #ifdef CK_ENCRYPTION
5261 case TELOPT_ENCRYPTION:
5262 if (ck_tn_sb_encrypt(sb, n) < 0) {
5263 if (TELOPT_U_MODE(x) == TN_NG_MU ||
5264 TELOPT_ME_MODE(x) == TN_NG_MU)
5267 whyclosed = WC_TELOPT;
5270 if (TELOPT_ME_MODE(x) == TN_NG_RQ)
5271 TELOPT_ME_MODE(x) = TN_NG_AC;
5272 if (TELOPT_U_MODE(x) == TN_NG_RQ)
5273 TELOPT_U_MODE(x) = TN_NG_AC;
5277 if (tn_sopt(WONT,x) < 0)
5282 if (tn_sopt(DONT,x) < 0)
5287 #endif /* CK_ENCRYPTION */
5290 return(iks_tn_sb(sb, n-2));
5291 #endif /* IKS_OPTION */
5293 case TELOPT_COMPORT:
5294 return(tnc_tn_sb(sb, n-2));
5295 #endif /* TN_COMPORT */
5298 case TELQUAL_SEND: /* SEND terminal type? */
5299 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
5300 if (tn_sttyp() < 0) /* Yes, so send it. */
5303 TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 1;
5306 case TELQUAL_IS: { /* IS terminal type? */
5307 /* IS terminal type -- remote gave us its current type */
5310 CHAR oldterm[64], *p;
5312 /* Isolate the specified terminal type string */
5313 while (sb[i++] != IAC) {
5314 if (i == 40 || /* max len of term string - RFC */
5322 strupr(&(sb[1])); /* Upper case it */
5323 for (i = 0; i <= max_tt; i++) { /* find it in our list */
5324 if (!strcmp(&(sb[1]),tt_info[i].x_name)
5325 && i != TT_VTNT) /* can't support VTNT as server */
5327 /* Set terminal type to the one chosen */
5334 strcmp(&(sb[1]),TELOPT_SB(TELOPT_TTYPE).term.type)) {
5335 /* Couldn't find the specified term type */
5337 strcpy(TELOPT_SB(TELOPT_TTYPE).term.type,&(sb[1]));
5339 tn_ssbopt(TELOPT_TTYPE,TELQUAL_SEND,NULL,0);
5340 TELOPT_UNANSWERED_SB(TELOPT_TTYPE)=1;
5344 p = (CHAR *) getenv("TERM");
5346 ckstrncpy((char *)oldterm,(char *)p,63);
5349 cklower((char *)&(sb[1])); /* Lower case new term */
5350 ckmakmsg(term_buf,64,"TERM=",(char *)&(sb[1]),NULL,NULL);
5354 #endif /* NOPUTENV */
5355 #endif /* OS2ORUNIX */
5360 if (tgetent(trmbuf,(char *)&sb[1]) < 1) {
5361 /* Unsupported terminal. If new and old terminal */
5362 /* types do not match, ask for another type. */
5363 if (strcmp((char *)oldterm,(char *)&sb[1])) {
5365 tn_ssbopt(TELOPT_TTYPE,TELQUAL_SEND,NULL,0);
5366 TELOPT_UNANSWERED_SB(TELOPT_TTYPE)=1;
5370 #endif /* COHERENT */
5371 #endif /* MYCURSES */
5372 #endif /* CK_CURSES */
5377 #ifdef CK_ENVIRONMENT
5379 case TELOPT_XDISPLOC: /* Send X-Display Location */
5380 if (sb[0] == TELQUAL_SEND) {/* SEND X-Display Loc? */
5381 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
5382 if (tn_sxdisploc() < 0) /* Yes, so send it. */
5385 TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 1;
5388 /* IS -- X Display Location (not supported) */
5389 else if (sb[0] == TELQUAL_IS) {
5391 /* Isolate the specified X-display string */
5392 while (sb[i++] != IAC) {
5400 debug(F110,"TELNET SB XDISPLOC IS",&sb[1],0);
5403 #endif /* CK_XDISPLOC */
5404 #endif /* CK_ENVIRONMENT */
5413 /* At this point sb[] should contain width and height */
5414 if (sb[i] == IAC) i++;
5415 w = (sb[i++] << 8); /* save upper height */
5416 if (sb[i] == IAC) i++;
5417 w += sb[i++]; /* save the width */
5418 if (sb[i] == IAC) i++;
5419 h = (sb[i++] << 8); /* save upper height */
5420 if (sb[i] == IAC) i++;
5422 debug(F111,"tn_doop NAWS SB","width",w);
5423 debug(F111,"tn_doop NAWS SB","height",h);
5430 if (tcp_incoming || inserver) {
5434 VscrnSetWidth(VTERM, w);
5435 VscrnSetHeight(VTERM, h+(tt_status[VTERM]?1:0));
5438 cmd_cols = tt_cols[VCMD] = w;
5439 cmd_rows = tt_rows[VCMD] = h;
5440 VscrnSetWidth(VCMD, w);
5441 VscrnSetHeight(VCMD, h);
5452 VscrnSetWidth(VCMD, w);
5453 VscrnSetHeight(VCMD, h);
5461 #endif /* NOLOCAL */
5463 /* Add LINES and COLUMNS to the environment */
5464 ckmakmsg((char *)rows_buf,16,"LINES=",ckitoa(h),NULL,NULL);
5465 ckmakmsg((char *)cols_buf,16,"COLUMNS=",ckitoa(w),NULL,NULL);
5470 #endif /* NOPUTENV */
5471 #endif /* OS2ORUNIX */
5474 #ifdef CK_ENVIRONMENT
5475 case TELOPT_NEWENVIRON:
5477 case TELQUAL_IS: /* IS */
5478 case TELQUAL_INFO: /* INFO */
5479 if (sb[0] == TELQUAL_IS)
5480 debug(F101,"tn_doop NEW-ENV SB IS","",n-3);
5482 debug(F101,"tn_doop NEW-ENV SB INFO","",n-3);
5483 if (sstelnet || inserver) { /* Yes, receive it. */
5484 if (tn_rnenv((CHAR *)&sb[1],n-3) < 0)
5488 case TELQUAL_SEND: /* SEND */
5489 if ( sstelnet || inserver ) /* ignore if server */
5491 /* We need to take the sb[] and build a structure */
5492 /* containing all of the variables and types that */
5493 /* we are supposed to keep track of and send to */
5494 /* the host, then call tn_snenv(). */
5495 /* Or we can punt ... */
5496 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
5497 if (tn_snenv((CHAR *)&sb[1],n-3) < 0) /* Yes, send it. */
5502 xxx = (CHAR *) malloc(n-1);
5504 unsigned char * xxx;
5505 xxx = (unsigned char *) malloc(n-1);
5507 /* Postpone sending until end of tn_ini() */
5508 TELOPT_SB(TELOPT_NEWENVIRON).env.str = xxx;
5509 if (TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
5510 memcpy((char *)TELOPT_SB(TELOPT_NEWENVIRON).env.str,
5511 (char *)&sb[1],n-3);
5512 TELOPT_SB(TELOPT_NEWENVIRON).env.str[n-3] = IAC;
5513 TELOPT_SB(TELOPT_NEWENVIRON).env.str[n-2] = '\0';
5514 TELOPT_SB(TELOPT_NEWENVIRON).env.len = n-3;
5515 TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 1;
5521 #endif /* CK_ENVIRONMENT */
5523 case TELOPT_SNDLOC: {
5526 debug(F110,"TELNET Send-Location",sb,0);
5530 #endif /* CK_SNDLOC */
5538 #ifdef CK_ANSIC /* TELNET DO OPTION */
5539 tn_doop(CHAR z, int echo, int (*fn)(int))
5541 tn_doop(z, echo, fn) CHAR z; int echo; int (*fn)();
5542 #endif /* CK_ANSIC */
5546 if (z != (CHAR) IAC) {
5547 debug(F101,"tn_doop bad call","",z);
5550 if (ttnet != NET_TCPB) /* Check network type */
5552 if (ttnproto != NP_TELNET &&
5553 ttnproto != NP_NONE) /* Check protocol */
5556 x = tn_xdoop(z,echo,fn);
5557 if (x >= 0 && !tn_begun) {
5560 return(y < 0 ? y : x);
5563 #ifdef CK_ENVIRONMENT
5565 /* Telnet receive new environment */
5566 /* Returns -1 on error, 0 if nothing happens, 1 on success */
5567 /* In order for this code to work, sb[len] == IAC */
5568 /* We currently only support the USER environment variable */
5572 tn_rnenv(CHAR * sb, int len)
5574 tn_rnenv(sb, len) CHAR * sb; int len;
5575 #endif /* CK_ANSIC */
5576 /* tn_rnenv */ { /* Receive new environment */
5579 char * reply = 0, * s = 0;
5580 int i,j,k,n; /* Worker. */
5581 int type = 0; /* 0 for NONE, 1 for VAR, 2 for USERVAR, */
5582 /* 3 for VALUE in progress */
5584 if (ttnet != NET_TCPB) return(0);
5585 if (ttnproto != NP_TELNET) return(0);
5586 if (sb == NULL) return(-1);
5588 if (len == 0) return(1);
5591 Pairs of <type> [VAR=0, VALUE=1, ESC=2, USERVAR=3] <value> "unterminated"
5592 follow here until done...
5594 for (i = 0, j = 0, k = 0, type = 0, varname[0]= '\0'; i <= len; i++) {
5596 case TEL_ENV_VAR: /* VAR */
5597 case TEL_ENV_USERVAR: /* USERVAR */
5598 case IAC: /* End of the list */
5600 case 0: /* Nothing in progress */
5601 /* If we get IAC only, then that means there were */
5602 /* no environment variables to send. we are done */
5603 if (j == 0 && sb[i] == IAC)
5605 case 1: /* VAR in progress */
5606 case 2: /* USERVAR in progress */
5607 case 3: /* VALUE in progress */
5610 debug(F111,"tn_rnenv varname",varname,type);
5611 debug(F111,"tn_rnenv value",value,type);
5612 if (!strcmp(varname,"USER")) {
5613 #ifdef CK_AUTHENTICATION
5614 if (ck_tn_auth_valid() != AUTH_VALID) {
5615 extern char szUserNameRequested[];
5616 debug(F100,"tn_rnenv != AUTH_VALID","",0);
5617 ckstrncpy(szUserNameRequested,value,UIDBUFLEN);
5618 ckstrncpy(uidbuf,value,UIDBUFLEN);
5620 if (ssl_active_flag) {
5621 if ( tls_is_user_valid(ssl_con, uidbuf) ) {
5622 extern char szUserNameAuthenticated[];
5623 ckstrncpy(szUserNameAuthenticated,uidbuf,
5625 auth_finished(AUTH_VALID);
5627 } else if (tls_active_flag) {
5628 if ( tls_is_user_valid(tls_con, uidbuf) ) {
5629 extern char szUserNameAuthenticated[];
5630 ckstrncpy(szUserNameAuthenticated,uidbuf,
5632 auth_finished(AUTH_VALID);
5636 } else { /* AUTH_VALID */
5638 debug(F110,"tn_rnenv AUTH_VALID uidbuf",uidbuf,0);
5641 x = ckstrcmp(value,uidbuf,-1,0); /* case insensitive */
5643 /* NTLM authentication returns names of the form */
5644 /* DOMAIN\user. We need to check to see of the */
5645 /* USER VAR contains a domain name or not. If */
5646 /* not, then we do not want to change state if */
5647 /* the uidbuf matches the USER VAR when the */
5648 /* DOMAIN is ignored. */
5649 if ( x && ck_tn_authenticated() == AUTHTYPE_NTLM ) {
5650 char * s1=NULL, * s2=NULL;
5653 len1 = strlen(value);
5654 for ( i=len1-1 ; i>=0 ; i--) {
5655 if ( value[i] == '\\' ) {
5656 s1 = &value[i+1]; /* DOMAIN found */
5662 len2 = strlen(uidbuf);
5663 for ( i=len2-1 ; i>=0 ; i--) {
5664 if ( uidbuf[i] == '\\' ) {
5665 s2 = &uidbuf[i+1]; /* DOMAIN found */
5671 x = ckstrcmp(value,s2,-1,0);
5676 x = ckstrcmp(value,uidbuf,-1,1); /* case sensitive */
5679 extern char szUserNameRequested[];
5680 ckstrncpy(uidbuf,value,UIDBUFLEN);
5681 ckstrncpy(szUserNameRequested,value,UIDBUFLEN);
5682 auth_finished(AUTH_USER);
5684 if (ssl_active_flag || tls_active_flag) {
5685 if ( tls_is_user_valid(ssl_con, uidbuf) )
5686 auth_finished(AUTH_VALID);
5691 #else /* CK_AUTHENTICATION */
5692 ckstrncpy(uidbuf,value,UIDBUFLEN);
5693 #endif /* CK_AUTHENTICATION */
5701 type = (sb[i] == TEL_ENV_USERVAR ? 2 : /* USERVAR */
5702 sb[i] == TEL_ENV_VAR ? 1 : /* VAR */
5706 case TEL_ENV_VALUE: /* VALUE */
5707 if ( type == 1 || type == 2 )
5710 case TEL_ENV_ESC: /* ESC */
5711 /* Take next character literally */
5714 /* otherwise, fallthrough so byte will be added to string. */
5717 case 1: /* VAR in progress */
5718 case 2: /* USERVAR in progress */
5720 varname[j++] = sb[i];
5732 /* These are for Microsoft SFU version 2 Telnet Server */
5733 #define SFUTLNTVER "SFUTLNTVER"
5734 #define SFUTLNTMODE "SFUTLNTMODE"
5735 #define SFUTLNTVER_VALUE "2"
5736 #define SFUTLNTMODE_VALUE "console" /* The other value is "stream" */
5738 /* Telnet send new environment */
5739 /* Returns -1 on error, 0 if nothing happens, 1 on success */
5740 /* In order for this code to work, sb[len] == IAC */
5744 tn_snenv(CHAR * sb, int len)
5746 tn_snenv(sb, len) CHAR * sb; int len;
5747 #endif /* CK_ANSIC */
5748 /* tn_snenv */ { /* Send new environment */
5750 char * reply = 0, * s = 0;
5751 int i,j,n; /* Worker. */
5752 int type = 0; /* 0 for NONE, 1 for VAR, 2 for USERVAR in progress */
5753 extern int ck_lcname;
5754 char localuidbuf[UIDBUFLEN]; /* (Initialized just below) */
5758 localuidbuf[0] = '\0';
5759 if (ttnet != NET_TCPB) return(0);
5760 if (ttnproto != NP_TELNET) return(0);
5761 if (!sb) return(-1);
5764 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
5770 if (TELOPT_U(TELOPT_FORWARD_X)) {
5773 #endif /* CK_FORWARD_X */
5774 disp = (char *)tn_get_display();
5777 ckstrncpy(localuidbuf,uidbuf,UIDBUFLEN);
5778 cklower(localuidbuf);
5782 hexdump((CHAR *)"tn_snenv sb[]",sb,len);
5783 debug(F110,"tn_snenv uidbuf",uidbuf,0);
5784 debug(F110,"tn_snenv localuidbuf",localuidbuf,0);
5785 debug(F110,"tn_snenv tn_env_sys",tn_env_sys,0);
5786 debug(F110,"tn_snenv tn_env_disp",tn_env_disp,0);
5787 debug(F110,"tn_snenv disp",disp,0);
5789 /* First determine the size of the buffer we will need */
5790 for (i = 0, j = 0, n = 0, type = 0, varname[0]= '\0'; i <= len; i++) {
5792 case TEL_ENV_VAR: /* VAR */
5793 case TEL_ENV_USERVAR: /* USERVAR */
5794 case IAC: /* End of the list */
5796 case 0: /* Nothing in progress */
5797 /* If we get IAC only, then that means send all */
5798 /* VAR and USERVAR. */
5799 if (!(j == 0 && sb[i] == IAC))
5801 case 1: /* VAR in progress */
5803 if (!varname[0]) { /* Send All */
5805 n += strlen(uu) + 4 + 2;
5807 n += strlen(tn_env_job) + 3 + 2;
5809 n += strlen(tn_env_acct) + 4 + 2;
5811 n += strlen(tn_env_prnt) + 7 + 2;
5813 n += strlen(tn_env_sys) + 10 + 2;
5815 n += strlen(disp) + 7 + 2;
5816 } else if (!strcmp(varname,"USER") && uu[0])
5817 n += strlen(uu) + 4 + 2;
5818 else if (!strcmp(varname,"JOB") && tn_env_job[0])
5819 n += strlen(tn_env_job) + 3 + 2;
5820 else if (!strcmp(varname,"ACCT") && tn_env_acct[0])
5821 n += strlen(tn_env_acct) + 4 + 2;
5822 else if (!strcmp(varname,"PRINTER") && tn_env_prnt[0])
5823 n += strlen(tn_env_prnt) + 7 + 2;
5824 else if (!strcmp(varname,"SYSTEMTYPE") && tn_env_sys[0])
5825 n += strlen(tn_env_sys) + 10 + 2;
5826 else if (!strcmp(varname,"DISPLAY") && disp)
5827 n += strlen(disp) + 7 + 2;
5828 /* If we get IAC only, then that means send all */
5829 /* VAR and USERVAR. */
5830 if (!(j == 0 && sb[i] == IAC))
5832 case 2: /* USERVAR in progress */
5834 if (!varname[0]) { /* Send All */
5836 for ( x=0 ; x<8 ; x++ ) {
5837 if ( tn_env_uservar[x][0] &&
5838 tn_env_uservar[x][1] )
5839 n += strlen(tn_env_uservar[x][0])
5840 + strlen(tn_env_uservar[x][1]) + 2;
5843 /* For compatibility with Microsoft Telnet Server */
5844 n += strlen(SFUTLNTVER) + strlen(SFUTLNTVER_VALUE) + 2;
5845 n += strlen(SFUTLNTMODE) +
5846 strlen(SFUTLNTMODE_VALUE) + 2;
5849 if ( tn_loc && tn_loc[0] )
5850 n += strlen("LOCATION") + strlen(tn_loc) + 2;
5851 #endif /* CK_SNDLOC */
5853 else if (tn_sfu && !strcmp(varname,SFUTLNTVER))
5854 n += strlen(SFUTLNTVER) + strlen(SFUTLNTVER_VALUE) + 2;
5855 else if (tn_sfu && !strcmp(varname,SFUTLNTMODE))
5856 n += strlen(SFUTLNTMODE) + strlen(SFUTLNTMODE_VALUE) + 2;
5858 else if ( tn_loc && tn_loc[0] && !strcmp(varname,"LOCATION"))
5859 n += strlen("LOCATION") + strlen(tn_loc) + 2;
5860 #endif /* CK_SNDLOC */
5863 for ( x=0 ; x<8 ; x++ ) {
5864 if ( tn_env_uservar[x][0] &&
5865 tn_env_uservar[x][1] &&
5866 !strcmp(varname,tn_env_uservar[x][0]))
5867 n += strlen(tn_env_uservar[x][0])
5868 + strlen(tn_env_uservar[x][1]) + 2;
5875 type = (sb[i] == TEL_ENV_USERVAR ? 2 : /* USERVAR */
5876 sb[i] == TEL_ENV_VAR ? 1 : /* VAR */
5880 case TEL_ENV_VALUE: /* VALUE */
5881 /* Protocol Error */
5882 debug(F100, "TELNET Subnegotiation error - VALUE in SEND", "",0);
5883 if (tn_deb || debses)
5884 tn_debug("TELNET Subnegotiation error - VALUE in SEND");
5886 case TEL_ENV_ESC: /* ESC */
5891 varname[j++] = sb[i];
5894 reply = malloc(n + 16); /* Leave room for IAC stuff */
5896 debug(F100, "TELNET Subnegotiation error - malloc failed", "",0);
5897 if (tn_deb || debses)
5898 tn_debug("TELNET Subnegotiation error - malloc failed");
5900 /* Send a return packet with no variables so that the host */
5901 /* may continue with additional negotiations */
5902 if (tn_ssbopt(TELOPT_NEWENVIRON,TELQUAL_IS,"",0) < 0)
5907 /* Now construct the real reply */
5909 n = 0; /* Start at beginning of buffer */
5911 Pairs of <type> [VAR=0, VALUE=1, ESC=2, USERVAR=3] <value> "unterminated"
5912 follow here until done...
5914 for (i = 0, j = 0, type = 0, varname[0]= '\0'; i <= len; i++) {
5916 case TEL_ENV_VAR: /* VAR */
5917 case TEL_ENV_USERVAR: /* USERVAR */
5918 case IAC: /* End of the list */
5920 case 0: /* Nothing in progress */
5921 /* If we get IAC only, then that means send all */
5922 /* VAR and USERVAR. */
5923 if (!(j == 0 && sb[i] == IAC))
5925 case 1: /* VAR in progress */
5930 reply[n] = TEL_ENV_VAR; /* VAR */
5931 strcpy(&reply[n+1],"USER");
5932 reply[n+5] = TEL_ENV_VALUE; /* VALUE */
5933 strcpy(&reply[n+6],uu);
5934 n += strlen(uu) + 4 + 2;
5936 if (tn_env_job[0]) {
5937 reply[n] = TEL_ENV_VAR; /* VAR */
5938 strcpy(&reply[n+1],"JOB");
5939 reply[n+4] = TEL_ENV_VALUE; /* VALUE */
5940 strcpy(&reply[n+5],tn_env_job);
5941 n += strlen(tn_env_job) + 3 + 2;
5943 if (tn_env_acct[0]) {
5944 reply[n] = TEL_ENV_VAR; /* VAR */
5945 strcpy(&reply[n+1],"ACCT");
5946 reply[n+5] = TEL_ENV_VALUE; /* VALUE */
5947 strcpy(&reply[n+6],tn_env_acct);
5948 n += strlen(tn_env_acct) + 4 + 2;
5950 if (tn_env_prnt[0]) {
5951 reply[n] = TEL_ENV_VAR; /* VAR */
5952 strcpy(&reply[n+1],"PRINTER");
5953 reply[n+8] = TEL_ENV_VALUE; /* VALUE */
5954 strcpy(&reply[n+9],tn_env_prnt);
5955 n += strlen(tn_env_prnt) + 7 + 2;
5957 if (tn_env_sys[0]) {
5958 reply[n] = TEL_ENV_VAR; /* VAR */
5959 strcpy(&reply[n+1],"SYSTEMTYPE");
5960 reply[n+11] = TEL_ENV_VALUE; /* VALUE */
5961 strcpy(&reply[n+12],tn_env_sys);
5962 n += strlen(tn_env_sys) + 10 + 2;
5965 reply[n] = TEL_ENV_VAR; /* VAR */
5966 strcpy(&reply[n+1],"DISPLAY");
5967 reply[n+8] = TEL_ENV_VALUE; /* VALUE */
5968 strcpy(&reply[n+9],disp);
5969 n += strlen(disp) + 7 + 2;
5971 } else if (!strcmp(varname,"USER") && uu[0]) {
5972 reply[n] = TEL_ENV_VAR; /* VAR */
5973 strcpy(&reply[n+1],"USER");
5974 reply[n+5] = TEL_ENV_VALUE; /* VALUE */
5975 strcpy(&reply[n+6],uu);
5976 n += strlen(uu) + 4 + 2;
5977 } else if (!strcmp(varname,"JOB") && tn_env_job[0]) {
5978 reply[n] = TEL_ENV_VAR; /* VAR */
5979 strcpy(&reply[n+1],"JOB");
5980 reply[n+4] = TEL_ENV_VALUE; /* VALUE */
5981 strcpy(&reply[n+5],tn_env_job);
5982 n += strlen(tn_env_job) + 3 + 2;
5983 } else if (!strcmp(varname,"ACCT") && tn_env_acct[0]) {
5984 reply[n] = TEL_ENV_VAR; /* VAR */
5985 strcpy(&reply[n+1],"ACCT");
5986 reply[n+5] = TEL_ENV_VALUE; /* VALUE */
5987 strcpy(&reply[n+6],tn_env_acct);
5988 n += strlen(tn_env_acct) + 4 + 2;
5989 } else if (!strcmp(varname,"PRINTER") && tn_env_prnt[0]) {
5990 reply[n] = TEL_ENV_VAR; /* VAR */
5991 strcpy(&reply[n+1],"PRINTER");
5992 reply[n+8] = TEL_ENV_VALUE; /* VALUE */
5993 strcpy(&reply[n+9],tn_env_prnt);
5994 n += strlen(tn_env_prnt) + 7 + 2;
5995 } else if (!strcmp(varname,"SYSTEMTYPE") && tn_env_sys[0]) {
5996 reply[n] = TEL_ENV_VAR; /* VAR */
5997 strcpy(&reply[n+1],"SYSTEMTYPE");
5998 reply[n+11] = TEL_ENV_VALUE; /* VALUE */
5999 strcpy(&reply[n+12],tn_env_sys);
6000 n += strlen(tn_env_sys) + 10 + 2;
6001 } else if (!strcmp(varname,"DISPLAY") && disp) {
6002 reply[n] = TEL_ENV_VAR; /* VAR */
6003 strcpy(&reply[n+1],"DISPLAY");
6004 reply[n+8] = TEL_ENV_VALUE; /* VALUE */
6005 strcpy(&reply[n+9],disp);
6006 n += strlen(disp) + 7 + 2;
6008 /* If we get IAC only, then that means send all */
6009 /* VAR and USERVAR. */
6010 if (!(j == 0 && sb[i] == IAC))
6012 case 2: /* USERVAR in progress */
6017 for ( x=0 ; x<8 ; x++ ) {
6018 if ( tn_env_uservar[x][0] &&
6019 tn_env_uservar[x][1] ) {
6020 reply[n] = TEL_ENV_USERVAR; /* VAR */
6021 y = strlen(tn_env_uservar[x][0]);
6022 strcpy(&reply[n+1],tn_env_uservar[x][0]);
6023 reply[n+y+1] = TEL_ENV_VALUE; /* VALUE */
6024 strcpy(&reply[n+y+2],tn_env_uservar[x][1]);
6025 n += y+strlen(tn_env_uservar[x][1])+2;
6029 /* Compatibility with Microsoft Telnet Server */
6030 reply[n] = TEL_ENV_USERVAR; /* VAR */
6031 strcpy(&reply[n+1],SFUTLNTVER);
6032 reply[n+11] = TEL_ENV_VALUE; /* VALUE */
6033 strcpy(&reply[n+12],SFUTLNTVER_VALUE);
6034 n += strlen(SFUTLNTVER)+strlen(SFUTLNTVER_VALUE)+2;
6036 reply[n] = TEL_ENV_USERVAR; /* VAR */
6037 strcpy(&reply[n+1],SFUTLNTMODE);
6038 reply[n+12] = TEL_ENV_VALUE; /* VALUE */
6039 strcpy(&reply[n+13],SFUTLNTMODE_VALUE);
6040 n += strlen(SFUTLNTMODE)+strlen(SFUTLNTMODE_VALUE)+2;
6042 if (tn_loc && tn_loc[0]) {
6043 reply[n] = TEL_ENV_USERVAR; /* VAR */
6044 strcpy(&reply[n+1],"LOCATION");
6045 reply[n+9] = TEL_ENV_VALUE; /* VALUE */
6046 strcpy(&reply[n+10],tn_loc);
6047 n += strlen("LOCATION") + strlen(tn_loc) + 2;
6049 } else if (tn_sfu && !strcmp(varname,SFUTLNTVER)) {
6050 reply[n] = TEL_ENV_USERVAR; /* VAR */
6051 strcpy(&reply[n+1],SFUTLNTVER);
6052 reply[n+11] = TEL_ENV_VALUE; /* VALUE */
6053 strcpy(&reply[n+12],SFUTLNTVER_VALUE);
6054 n += strlen(SFUTLNTVER) + strlen(SFUTLNTVER_VALUE) + 2;
6055 } else if (tn_sfu && !strcmp(varname,SFUTLNTMODE)) {
6056 reply[n] = TEL_ENV_USERVAR; /* VAR */
6057 strcpy(&reply[n+1],SFUTLNTMODE);
6058 reply[n+12] = TEL_ENV_VALUE; /* VALUE */
6059 strcpy(&reply[n+13],SFUTLNTMODE_VALUE);
6060 n += strlen(SFUTLNTMODE) + strlen(SFUTLNTMODE_VALUE) + 2;
6063 else if (tn_loc && tn_loc[0] && !strcmp(varname,"LOCATION")){
6064 reply[n] = TEL_ENV_USERVAR; /* VAR */
6065 strcpy(&reply[n+1],"LOCATION");
6066 reply[n+9] = TEL_ENV_VALUE; /* VALUE */
6067 strcpy(&reply[n+10],tn_loc);
6068 n += strlen("LOCATION") + strlen(tn_loc) + 2;
6070 #endif /* CK_SNDLOC */
6073 for ( x=0 ; x<8 ; x++ ) {
6074 if ( tn_env_uservar[x][0] &&
6075 tn_env_uservar[x][1] &&
6076 !strcmp(varname,tn_env_uservar[x][0])) {
6077 reply[n] = TEL_ENV_USERVAR; /* VAR */
6078 y = strlen(tn_env_uservar[x][0]);
6079 strcpy(&reply[n+1],tn_env_uservar[x][0]);
6080 reply[n+y+1] = TEL_ENV_VALUE; /* VALUE */
6081 strcpy(&reply[n+y+2],tn_env_uservar[x][1]);
6082 n += y+strlen(tn_env_uservar[x][1])+2;
6090 type = (sb[i] == TEL_ENV_USERVAR ? 2 : /* USERVAR */
6091 sb[i] == TEL_ENV_VAR ? 1 : /* VAR */
6095 case TEL_ENV_VALUE: /* VALUE */
6096 /* Protocol Error */
6097 debug(F100, "TELNET Subnegotiation error - VALUE in SEND", "",0);
6098 if (tn_deb || debses)
6099 tn_debug("TELNET Subnegotiation error - VALUE in SEND");
6100 return(0); /* Was -1 but that would be taken as */
6101 /* an I/O error, so absorb it and go on. */
6102 case TEL_ENV_ESC: /* ESC */
6103 /* Not sure what this for. Quote next character? */
6106 varname[j++] = sb[i];
6109 if (tn_ssbopt(TELOPT_NEWENVIRON,TELQUAL_IS,reply,n) < 0) {
6116 #endif /* CK_ENVIRONMENT */
6118 /* Telnet send terminal type */
6119 /* Returns -1 on error, 0 if nothing happens, 1 if type sent successfully */
6122 tn_sttyp() { /* Send telnet terminal type. */
6123 char *ttn; /* Name of terminal type. */
6125 static int alias = -1; /* which alias are we using ? */
6128 int i, rc; /* Worker. */
6131 if (ttnet != NET_TCPB) return(0);
6132 if (ttnproto != NP_TELNET) return(0);
6134 if (!TELOPT_ME(TELOPT_TTYPE)) return(0);
6137 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6150 } else if (ttnumend) {
6154 if (tt_info[tt_type].x_aliases[++alias] == NULL) {
6157 if (ttnum == tt_type)
6163 if (tt_type >= 0 && tt_type <= max_tt) {
6165 ttn = tt_info[tt_type].x_name;
6167 ttn = tt_info[tt_type].x_aliases[alias];
6175 if (tn_term) { /* Terminal type override? */
6176 debug(F110,"tn_sttyp",tn_term,0);
6181 } else debug(F100,"tn_sttyp no term override","",0);
6184 if (!ttn) { /* If no override, */
6185 ttn = getenv("TERM"); /* get it from the environment. */
6187 #endif /* datageneral */
6188 if ((ttn == ((char *)0)) || ((int)strlen(ttn) >= TSBUFSIZ))
6190 sb_out[0] = (CHAR) IAC; /* I Am a Command */
6191 sb_out[1] = (CHAR) SB; /* Subnegotiation */
6192 sb_out[2] = TELOPT_TTYPE; /* Terminal Type */
6193 sb_out[3] = (CHAR) 0; /* Is... */
6194 for (i = 4; *ttn; ttn++,i++) { /* Copy and uppercase it */
6196 if (!tntermflg && *ttn == '-' &&
6197 (!strcmp(ttn,"-80") || !strcmp(ttn,"-132")))
6201 sb_out[i] = (char) ((!tntermflg && islower(*ttn)) ?
6205 ttn = (char *)sb_out; /* Point back to beginning */
6207 if (deblog || tn_deb || debses) {
6208 sb_out[i] = '\0'; /* For debugging */
6209 ckmakxmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
6210 TELOPT(TELOPT_TTYPE)," IS ",(char *)sb_out+4," IAC SE",
6211 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
6214 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
6215 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
6217 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
6220 debug(F100,tn_msg_out,"",0);
6221 if (tn_deb || debses) tn_debug(tn_msg_out);
6223 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
6225 ReleaseTelnetMutex();
6232 settermtype(tt_type,0);
6235 VscrnIsDirty(VTERM);
6242 #ifdef CK_ENVIRONMENT
6245 /* Telnet send xdisplay location */
6246 /* Returns -1 on error, 0 if nothing happens, 1 if type sent successfully */
6249 tn_sxdisploc() { /* Send telnet X display location. */
6253 if (ttnet != NET_TCPB) return(0);
6254 if (ttnproto != NP_TELNET) return(0);
6256 if (!TELOPT_ME(TELOPT_XDISPLOC)) return(0);
6259 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6265 if (TELOPT_U(TELOPT_FORWARD_X)) {
6268 #endif /* CK_FORWARD_X */
6269 disp = (char *)tn_get_display();
6270 debug(F110,"tn_sxdisploc",disp,0);
6273 /* Can't do both, send WONT */
6274 if (tn_sopt(WONT,TELOPT_XDISPLOC) < 0)
6276 TELOPT_UNANSWERED_WONT(TELOPT_XDISPLOC) = 1;
6280 sb_out[0] = (CHAR) IAC; /* I Am a Command */
6281 sb_out[1] = (CHAR) SB; /* Subnegotiation */
6282 sb_out[2] = TELOPT_XDISPLOC; /* X-Display Location */
6283 sb_out[3] = (CHAR) 0; /* Is... */
6284 for (i = 4; *disp; disp++,i++) { /* Copy and uppercase it */
6285 sb_out[i] = (char) *disp;
6288 if (deblog || tn_deb || debses) {
6289 sb_out[i] = '\0'; /* For debugging */
6290 ckmakxmsg( tn_msg_out,TN_MSG_LEN,
6291 "TELNET SENT SB ",TELOPT(TELOPT_XDISPLOC),
6292 " IS ",(char *)sb_out+4," IAC SE",
6293 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
6296 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
6297 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
6299 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
6302 debug(F100,tn_msg_out,"",0);
6303 if (tn_deb || debses) tn_debug(tn_msg_out);
6305 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
6307 ReleaseTelnetMutex();
6313 #endif /* CK_XDISPLOC */
6314 #endif /* CK_ENVIRONMENT */
6318 tn_sndfwdx() { /* Send Fwd X Screen number to host */
6319 unsigned char screen = 0;
6323 if (!TELOPT_U(TELOPT_FORWARD_X)) return(0);
6325 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6331 * The format of the DISPLAY variable is [<host>:]<display>[.<screen>]
6332 * where <host> is an optional DNS name or ip address with a default of
6333 * the localhost; the screen defaults to 0
6336 disp = tn_get_display();
6339 colon = ckindex(":",disp,0,0,1);
6340 dot = ckindex(".",&disp[colon],0,0,1);
6343 screen = atoi(&disp[colon+dot]);
6350 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
6351 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
6352 sb_out[i++] = TELOPT_FORWARD_X; /* Forward X */
6353 sb_out[i++] = FWDX_SCREEN; /* Screen */
6354 sb_out[i++] = screen;
6355 if ( screen == IAC )
6357 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
6358 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
6360 if (deblog || tn_deb || debses) {
6361 ckmakxmsg( tn_msg_out,TN_MSG_LEN,
6362 "TELNET SENT SB ",TELOPT(TELOPT_FORWARD_X),
6363 " SCREEN ",ckctox(screen,1)," IAC SE",
6364 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
6368 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
6371 debug(F100,tn_msg_out,"",0);
6372 if (tn_deb || debses) tn_debug(tn_msg_out);
6374 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
6376 ReleaseTelnetMutex();
6382 #endif /* CK_FORWARD_X */
6386 tn_sndloc() { /* Send location. */
6387 int i,rc; /* Worker. */
6390 if (!TELOPT_ME(TELOPT_SNDLOC)) return(0);
6393 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6397 ttloc = (tn_loc ? tn_loc : ""); /* In case we are being called even */
6398 /* though there is no location. */
6399 sb_out[0] = (CHAR) IAC; /* I Am a Command */
6400 sb_out[1] = (CHAR) SB; /* Subnegotiation */
6401 sb_out[2] = TELOPT_SNDLOC; /* Location */
6402 for (i = 3; *ttloc && i < TSBUFSIZ; ttloc++,i++) /* Copy it */
6403 sb_out[i] = (char) *ttloc;
6404 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
6405 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
6408 if (deblog || tn_deb || debses) {
6409 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
6410 "TELNET SENT SB ",TELOPT(TELOPT_SNDLOC)," ",(char *)sb_out+3,
6411 " IAC SE", NULL,NULL,NULL,NULL,NULL,NULL,NULL);
6415 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
6418 debug(F100,tn_msg_out,"",0);
6419 if (tn_deb || debses) tn_debug(tn_msg_out);
6421 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
6423 ReleaseTelnetMutex();
6427 sb_out[i-2] = '\0'; /* For debugging */
6430 #endif /* CK_SNDLOC */
6432 #ifdef CK_NAWS /* NAWS = Negotiate About Window Size */
6434 tn_snaws() { /* Send terminal width and height, RFC 1073 */
6436 CHAR sb_out[24]; /* multiple threads */
6439 int x = VscrnGetWidth(VTERM),
6440 y = VscrnGetHeight(VTERM) - (tt_status[VTERM] ? 1 : 0);
6442 int x = tt_cols, y = tt_rows;
6445 if (ttnet != NET_TCPB) return(0);
6446 if (ttnproto != NP_TELNET) return(0);
6447 if (!TELOPT_ME(TELOPT_NAWS)) return(0);
6450 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6457 if (x == TELOPT_SB(TELOPT_NAWS).naws.x && /* Only send if changed */
6458 y == TELOPT_SB(TELOPT_NAWS).naws.y
6461 TELOPT_SB(TELOPT_NAWS).naws.x = x; /* Remember the size */
6462 TELOPT_SB(TELOPT_NAWS).naws.y = y;
6464 sb_out[i++] = (CHAR) IAC; /* Send the subnegotiation */
6465 sb_out[i++] = (CHAR) SB;
6466 sb_out[i++] = TELOPT_NAWS;
6467 sb_out[i++] = (CHAR) (x >> 8) & 0xff;
6468 if ((CHAR) sb_out[i-1] == (CHAR) IAC) /* IAC in data must be doubled */
6469 sb_out[i++] = (CHAR) IAC;
6470 sb_out[i++] = (CHAR) (x & 0xff);
6471 if ((CHAR) sb_out[i-1] == (CHAR) IAC)
6472 sb_out[i++] = (CHAR) IAC;
6473 sb_out[i++] = (CHAR) (y >> 8) & 0xff;
6474 if ((CHAR) sb_out[i-1] == (CHAR) IAC)
6475 sb_out[i++] = (CHAR) IAC;
6476 sb_out[i++] = (CHAR) (y & 0xff);
6477 if ((CHAR) sb_out[i-1] == (CHAR) IAC)
6478 sb_out[i++] = (CHAR) IAC;
6479 sb_out[i++] = (CHAR) IAC;
6480 sb_out[i++] = (CHAR) SE;
6482 if (deblog || tn_deb || debses) {
6483 ckmakxmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB NAWS ",
6484 ckitoa(x)," ",ckitoa(y)," IAC SE",
6485 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
6489 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
6492 debug(F100,tn_msg_out,"",0);
6493 if (tn_deb || debses) tn_debug(tn_msg_out);
6495 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
6497 ReleaseTelnetMutex();
6501 #endif /* NOLOCAL */
6504 #endif /* CK_NAWS */
6507 static char * tnc_signature = NULL;
6508 static int tnc_ls_mask = 0;
6509 static int tnc_ls = 0;
6510 static int tnc_ms_mask = 255;
6511 static int tnc_ms = 0;
6512 static int tnc_oflow = 0;
6513 static int tnc_iflow = 0;
6514 static int tnc_bps = 0;
6515 static int tnc_datasize = 0;
6516 static int tnc_parity = 0;
6517 static int tnc_stopbit = 0;
6518 static int tnc_break = 0;
6519 static int tnc_dtr = 0;
6520 static int tnc_rts = 0;
6521 static int tnc_suspend_xmit = 0;
6522 static int tnc_bps_index = -1;
6527 #else /* CK_ANSIC */
6529 #endif /* CK_ANSIC */
6531 debug(F100,"tnc_init","",0);
6533 if (tnc_signature) {
6534 free(tnc_signature);
6535 tnc_signature = NULL;
6550 tnc_suspend_xmit = 0;
6558 #else /* CK_ANSIC */
6560 #endif /* CK_ANSIC */
6561 /* tn_sndcomport */ {
6562 int baud, datasize, parity, stopsize, oflow, iflow;
6563 CONST char * signature;
6565 debug(F100,"tnc_sndcomport","",0);
6566 signature = tnc_get_signature();
6567 baud = tnc_get_baud();
6568 datasize = tnc_get_datasize();
6569 parity = tnc_get_parity();
6570 stopsize = tnc_get_stopsize();
6571 oflow = tnc_get_oflow();
6572 iflow = tnc_get_iflow();
6573 tnc_set_ls_mask(255);
6574 tnc_set_ms_mask(255);
6580 tnc_wait(CHAR * msg, int ms)
6581 #else /* CK_ANSIC */
6582 tnc_wait(msg, ms) CHAR * msg; int ms;
6583 #endif /* CK_ANSIC */
6585 int rc, tn_wait_save = tn_wait_flg;
6586 debug(F111,"tnc_wait","begin",ms);
6588 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms = 1;
6590 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 1;
6592 rc = tn_wait((char *)msg);
6594 debug(F110,"tnc_wait","end",0);
6595 tn_wait_flg = tn_wait_save;
6599 /* Returns -1 on error, 0 on success */
6600 /* In order for this code to work, sb[len] == IAC */
6604 tnc_tn_sb(CHAR * sb, int len)
6606 tnc_tn_sb(sb, len) CHAR * sb; int len;
6607 #endif /* CK_ANSIC */
6609 if (ttnet != NET_TCPB) return(0);
6610 if (ttnproto != NP_TELNET) return(0);
6611 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
6613 if (!sb) return(-1);
6616 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6621 debug(F111,"tnc_tn_sb","sb[0]",sb[0]);
6622 debug(F111,"tnc_tn_sb","len",len);
6625 case TNC_C2S_SIGNATURE:
6626 case TNC_S2C_SIGNATURE:
6627 debug(F111,"tnc_tn_sb","signature",len);
6629 tnc_send_signature("Kermit Telnet Com Port Option");
6631 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6633 free(tnc_signature);
6634 tnc_signature = malloc(len);
6635 if (tnc_signature) {
6636 memcpy(tnc_signature,&sb[1],len-1);
6637 tnc_signature[len-1] = '\0';
6642 case TNC_C2S_SET_BAUDRATE:
6643 case TNC_S2C_SET_BAUDRATE: {
6645 char * br = (char *)&baudrate;
6646 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6648 /* Actual behavior of the Access Server... */
6649 debug(F111,"tnc_tn_sb","baudrate index",sb[1]);
6685 case TNC_BPS_115200:
6688 case TNC_BPS_230400:
6691 case TNC_BPS_460800:
6697 } else if (len == 5) {
6698 /* This section attempts to follow RFC 2217 */
6705 /* AOS/VS doesn't have ntohl() but MV's are big-endian */
6708 tnc_bps = ntohl(baudrate);
6709 #endif /* datageneral */
6710 debug(F111,"tnc_tn_sb","baudrate rfc",tnc_bps);
6712 debug(F111,"tnc_tn_sb","baudrate invalid len",len);
6717 case TNC_C2S_SET_DATASIZE:
6718 case TNC_S2C_SET_DATASIZE:
6719 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6722 tnc_datasize = sb[1];
6723 debug(F111,"tnc_tn_sb","datasize",sb[1]);
6726 case TNC_C2S_SET_PARITY:
6727 case TNC_S2C_SET_PARITY:
6728 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6732 debug(F111,"tnc_tn_sb","parity",sb[1]);
6735 case TNC_C2S_SET_STOPSIZE:
6736 case TNC_S2C_SET_STOPSIZE:
6737 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6740 tnc_stopbit = sb[1];
6741 debug(F111,"tnc_tn_sb","stopsize",sb[1]);
6744 case TNC_C2S_SET_CONTROL:
6745 case TNC_S2C_SET_CONTROL:
6747 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6752 /* This line should be removed when testing is complete. */
6753 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6754 #endif /* COMMENT */
6757 case TNC_CTL_OFLOW_REQUEST:
6758 /* determine local outbound flow control and send to peer */
6759 /* Cisco IOS returns 0 (TNC_CTL_OFLOW_REQUEST) when attempting */
6760 /* to set the inbound flow control if it is not supported */
6761 /* separately from outbound flow control. So must reset */
6762 /* wait for sb flag. */
6763 debug(F110,"tnc_tn_sb","oflow request",0);
6764 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6766 case TNC_CTL_OFLOW_NONE:
6767 case TNC_CTL_OFLOW_XON_XOFF:
6768 case TNC_CTL_OFLOW_RTS_CTS:
6769 case TNC_CTL_OFLOW_DCD:
6770 case TNC_CTL_OFLOW_DSR:
6771 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6773 debug(F111,"tnc_tn_sb","oflow",sb[1]);
6775 case TNC_CTL_BREAK_REQUEST:
6776 /* determine local break state and send to peer */
6777 debug(F110,"tnc_tn_sb","break request",0);
6779 case TNC_CTL_BREAK_ON:
6780 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6782 debug(F110,"tnc_tn_sb","break on",0);
6785 case TNC_CTL_BREAK_OFF:
6786 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6788 debug(F110,"tnc_tn_sb","break off",0);
6791 case TNC_CTL_DTR_REQUEST:
6792 /* determine local dtr state and send to peer */
6793 debug(F110,"tnc_tn_sb","dtr request",0);
6796 case TNC_CTL_DTR_ON:
6797 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6799 debug(F110,"tnc_tn_sb","dtr on",0);
6802 case TNC_CTL_DTR_OFF:
6803 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6805 debug(F110,"tnc_tn_sb","dtr off",0);
6808 case TNC_CTL_RTS_REQUEST:
6809 /* determine local rts state and send to peer */
6810 debug(F110,"tnc_tn_sb","rts request",0);
6813 case TNC_CTL_RTS_ON:
6814 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6816 debug(F110,"tnc_tn_sb","rts on",0);
6819 case TNC_CTL_RTS_OFF:
6820 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6822 debug(F110,"tnc_tn_sb","rts off",0);
6825 case TNC_CTL_IFLOW_REQUEST:
6826 /* determine local inbound flow control and send to peer */
6827 debug(F110,"tnc_tn_sb","iflow request",0);
6830 case TNC_CTL_IFLOW_NONE:
6831 case TNC_CTL_IFLOW_XON_XOFF:
6832 case TNC_CTL_IFLOW_RTS_CTS:
6833 case TNC_CTL_IFLOW_DTR:
6834 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6836 debug(F111,"tnc_tn_sb","iflow",sb[1]);
6843 case TNC_C2S_NOTIFY_LINESTATE:
6844 case TNC_S2C_SEND_LS:
6848 debug(F111,"tnc_tn_sb","linestate",sb[1]);
6849 if (tn_deb || debses) {
6850 if (tnc_ls & TNC_MS_DATA_READY )
6851 tn_debug(" ComPort Linestate Data Ready");
6852 if (tnc_ls & TNC_MS_OVERRUN_ERROR )
6853 tn_debug(" ComPort Linestate Overrun Error");
6854 if (tnc_ls & TNC_MS_PARITY_ERROR )
6855 tn_debug(" ComPort Linestate Parity Error");
6856 if (tnc_ls & TNC_MS_FRAME_ERROR )
6857 tn_debug(" ComPort Linestate Framing Error");
6858 if (tnc_ls & TNC_MS_BREAK_ERROR )
6859 tn_debug(" ComPort Linestate Break Detect Error");
6860 if (tnc_ls & TNC_MS_HR_EMPTY )
6861 tn_debug(" ComPort Linestate Holding Register Empty");
6862 if (tnc_ls & TNC_MS_SR_EMPTY )
6863 tn_debug(" ComPort Linestate Shift Register Empty");
6864 if (tnc_ls & TNC_MS_TIMEOUT_ERROR )
6865 tn_debug(" ComPort Linestate Timeout Error");
6869 case TNC_C2S_NOTIFY_MODEMSTATE:
6870 case TNC_S2C_SEND_MS:
6871 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms = 0;
6875 debug(F111,"tnc_tn_sb","modemstate",sb[1]);
6876 if (tn_deb || debses) {
6877 if (tnc_ms & TNC_MS_CTS_DELTA )
6878 tn_debug(" ComPort Modemstate CTS State Change");
6879 if (tnc_ms & TNC_MS_DSR_DELTA )
6880 tn_debug(" ComPort Modemstate DSR State Change");
6881 if (tnc_ms & TNC_MS_EDGE_RING )
6882 tn_debug(" ComPort Modemstate Trailing Edge Ring Detector On");
6884 tn_debug(" ComPort Modemstate Trailing Edge Ring Detector Off");
6885 if (tnc_ms & TNC_MS_RLSD_DELTA )
6886 tn_debug(" ComPort Modemstate RLSD State Change");
6887 if (tnc_ms & TNC_MS_CTS_SIG )
6888 tn_debug(" ComPort Modemstate CTS Signal On");
6890 tn_debug(" ComPort Modemstate CTS Signal Off");
6891 if (tnc_ms & TNC_MS_DSR_SIG )
6892 tn_debug(" ComPort Modemstate DSR Signal On");
6894 tn_debug(" ComPort Modemstate DSR Signal Off");
6895 if (tnc_ms & TNC_MS_RI_SIG )
6896 tn_debug(" ComPort Modemstate Ring Indicator On");
6898 tn_debug(" ComPort Modemstate Ring Indicator Off");
6899 if (tnc_ms & TNC_MS_RLSD_SIG )
6900 tn_debug(" ComPort Modemstate RLSD Signal On");
6902 tn_debug(" ComPort Modemstate RLSD Signal Off");
6906 case TNC_C2S_FLOW_SUSPEND:
6907 case TNC_S2C_FLOW_SUSPEND:
6908 debug(F110,"tnc_tn_sb","flow suspend",0);
6909 tnc_suspend_xmit = 1;
6912 case TNC_C2S_FLOW_RESUME:
6913 case TNC_S2C_FLOW_RESUME:
6914 debug(F110,"tnc_tn_sb","flow resume",0);
6915 tnc_suspend_xmit = 0;
6918 case TNC_C2S_SET_LS_MASK:
6919 case TNC_S2C_SET_LS_MASK:
6920 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6923 debug(F111,"tnc_tn_sb","linestate mask",sb[1]);
6924 tnc_ls_mask = sb[1];
6927 case TNC_C2S_SET_MS_MASK:
6928 case TNC_S2C_SET_MS_MASK:
6929 TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
6932 debug(F111,"tnc_tn_sb","modemstate mask",sb[1]);
6933 tnc_ls_mask = sb[1];
6940 debug(F111,"tnc_tn_sb","purge",sb[1]);
6942 case TNC_PURGE_RECEIVE:
6943 case TNC_PURGE_TRANSMIT:
6944 case TNC_PURGE_BOTH:
6945 /* purge local buffers */
6959 tnc_get_signature(void)
6960 #else /* CK_ANSIC */
6962 #endif /* CK_ANSIC */
6963 /* tnc_get_signature */ {
6964 /* send IAC SB COM-PORT SIGNATURE IAC SE */
6965 /* wait for response */
6968 if (ttnet != NET_TCPB) return(NULL);
6969 if (ttnproto != NP_TELNET) return(NULL);
6971 if (!TELOPT_ME(TELOPT_COMPORT)) return(NULL);
6974 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
6979 if ( tnc_signature )
6980 return(tnc_signature);
6982 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
6983 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
6984 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
6985 sb_out[i++] = TNC_C2S_SIGNATURE; /* Signature */
6986 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
6987 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
6990 if (deblog || tn_deb || debses) {
6991 ckmakmsg(tn_msg_out,TN_MSG_LEN,
6992 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
6993 " SIGNATURE IAC SE", NULL);
6997 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7000 debug(F100,tn_msg_out,"",0);
7001 if (tn_deb || debses) tn_debug(tn_msg_out);
7003 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7005 ReleaseTelnetMutex();
7010 if (tnc_wait((CHAR *)"comport signature request",0) < 0) {
7014 debug(F110,"tnc_get_signature",tnc_signature,0);
7015 return(tnc_signature);
7020 tnc_send_signature(char * signature)
7021 #else /* CK_ANSIC */
7022 tnc_send_signature(signature) char * signature;
7023 #endif /* CK_ANSIC */
7024 /* tnc_send_signature */ {
7025 /* send IAC SB COM-PORT SIGNATURE <text> IAC SE */
7026 int i = 0, j = 0, rc;
7028 debug(F110,"tnc_send_signature",signature,0);
7030 if (!signature || !signature[0])
7033 if (ttnet != NET_TCPB) return(0);
7034 if (ttnproto != NP_TELNET) return(0);
7036 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7039 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7044 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7045 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7046 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7047 sb_out[i++] = TNC_C2S_SIGNATURE; /* Signature */
7048 for (; signature[j]; i++,j++)
7049 sb_out[i] = signature[j];
7050 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7051 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7054 if (deblog || tn_deb || debses) {
7055 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7056 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7057 " SIGNATURE ", signature, " IAC SE", NULL,
7058 NULL,NULL,NULL,NULL,NULL,NULL);
7062 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7065 debug(F100,tn_msg_out,"",0);
7066 if (tn_deb || debses) tn_debug(tn_msg_out);
7068 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7070 ReleaseTelnetMutex();
7079 tnc_set_baud( long baud )
7080 #else /* CK_ANSIC */
7081 tnc_set_baud(baud) long baud;
7082 #endif /* CK_ANSIC */
7083 /* tnc_set_baud */ {
7084 /* send IAC SB COM-PORT SET-BAUD <value(4)> IAC SE */
7085 /* wait for response */
7086 /* 0 is used to request the current baud rate and */
7087 /* may not be sent by this func */
7088 /* return new host value */
7091 * the above comes from the RFC. But that is not what I am seeing
7092 * instead I appear to be seeing to following:
7115 /* AOS/VS doesn't have htonl() but MV's are big-endian */
7116 long net_baud = baud;
7118 long net_baud = htonl(baud);
7119 #endif /* datageneral */
7122 debug(F111,"tnc_set_baud","begin",baud);
7124 if (ttnet != NET_TCPB) return(0);
7125 if (ttnproto != NP_TELNET) return(0);
7127 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7130 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7138 if ( net_baud != 0 && net_baud == tnc_bps)
7141 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7142 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7143 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7144 sb_out[i++] = TNC_C2S_SET_BAUDRATE; /* Set Baud Rate */
7146 if (tnc_bps_index) {
7147 /* IOS Access Server */
7150 else if (baud <= 600)
7152 else if (baud <= 1200)
7154 else if (baud <= 2400)
7156 else if (baud <= 4800)
7158 else if (baud <= 9600)
7160 else if (baud <= 14400)
7162 else if (baud <= 19200)
7164 else if (baud <= 28800)
7166 else if (baud <= 38400)
7168 else if (baud <= 57600)
7170 else if (baud <= 115200)
7172 else if (baud <= 230400)
7179 sb_out[i++] = ((char *)&net_baud)[0];
7180 sb_out[i++] = ((char *)&net_baud)[1];
7181 sb_out[i++] = ((char *)&net_baud)[2];
7182 sb_out[i++] = ((char *)&net_baud)[3];
7184 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7185 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7188 if (deblog || tn_deb || debses) {
7189 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7190 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7191 " SET-BAUD-RATE ", ckltoa(baud)," IAC SE", NULL,
7192 NULL,NULL,NULL,NULL,NULL,NULL);
7197 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7200 debug(F100,tn_msg_out,"",0);
7201 if (tn_deb || debses) tn_debug(tn_msg_out);
7203 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7205 ReleaseTelnetMutex();
7210 if (tnc_wait((CHAR *)"comport set baud rate",0) < 0) {
7214 debug(F111,"tnc_set_baud","end",tnc_bps);
7221 #else /* CK_ANSIC */
7223 #endif /* CK_ANSIC */
7224 /* tnc_get_baud */ {
7225 /* send IAC SB COM-PORT SET-BAUD <value(4)=0> IAC SE */
7226 /* wait for response */
7229 debug(F110,"tnc_get_baud","begin",0);
7231 if (ttnet != NET_TCPB) return(0);
7232 if (ttnproto != NP_TELNET) return(0);
7234 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7237 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7242 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7243 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7244 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7245 sb_out[i++] = TNC_C2S_SET_BAUDRATE; /* Set Baud Rate */
7247 if (tnc_bps_index > 0) {
7257 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7258 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7261 if (deblog || tn_deb || debses) {
7262 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7263 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7264 " SET-BAUD-RATE ", ckltoa(0)," IAC SE", NULL,
7265 NULL,NULL,NULL,NULL,NULL,NULL);
7269 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7272 debug(F100,tn_msg_out,"",0);
7273 if (tn_deb || debses) tn_debug(tn_msg_out);
7275 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7277 ReleaseTelnetMutex();
7282 if (tnc_wait((CHAR *)"comport get baud rate",0) < 0) {
7286 debug(F111,"tnc_get_baud","end",tnc_bps);
7292 tnc_set_datasize(int datasize)
7293 #else /* CK_ANSIC */
7294 tnc_set_datasize(datasize) int datasize;
7295 #endif /* CK_ANSIC */
7296 /* tnc_set_datasize */ {
7297 /* IAC SB COM-PORT SET_DATASIZE <value(1)> IAC SE */
7298 /* Valid <value>s are 5 through 8 */
7299 /* Wait for response */
7300 /* return new host value */
7304 debug(F111,"tnc_set_datasize","begin",datasize);
7306 if (ttnet != NET_TCPB) return(0);
7307 if (ttnproto != NP_TELNET) return(0);
7309 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7312 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7317 if ( !(datasize >= 5 && datasize <= 8) )
7320 if ( datasize != 0 && datasize == tnc_datasize )
7321 return(tnc_datasize);
7323 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7324 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7325 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7326 sb_out[i++] = TNC_C2S_SET_DATASIZE; /* Set DataSize */
7327 sb_out[i++] = (unsigned char)(datasize & 0xFF);
7328 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7329 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7332 if (deblog || tn_deb || debses) {
7333 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7334 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7335 " SET-DATASIZE ", ckitoa(datasize)," IAC SE", NULL,
7336 NULL,NULL,NULL,NULL,NULL,NULL);
7340 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7343 debug(F100,tn_msg_out,"",0);
7344 if (tn_deb || debses) tn_debug(tn_msg_out);
7346 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7348 ReleaseTelnetMutex();
7353 if (tnc_wait((CHAR *)"comport set datasize",0) < 0) {
7357 debug(F111,"tnc_set_datasize","end",tnc_datasize);
7358 return(tnc_datasize);
7363 tnc_get_datasize(void)
7364 #else /* CK_ANSIC */
7366 #endif /* CK_ANSIC */
7367 /* tnc_get_datasize */ {
7368 /* IAC SB COM-PORT SET_DATASIZE <value(1)=0> IAC SE */
7369 /* Wait for response */
7372 debug(F110,"tnc_get_datasize","begin",0);
7374 if (ttnet != NET_TCPB) return(0);
7375 if (ttnproto != NP_TELNET) return(0);
7377 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7380 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7385 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7386 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7387 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7388 sb_out[i++] = TNC_C2S_SET_DATASIZE; /* Set DataSize */
7390 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7391 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7394 if (deblog || tn_deb || debses) {
7395 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7396 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7397 " SET-DATASIZE ", ckltoa(0)," IAC SE", NULL,
7398 NULL,NULL,NULL,NULL,NULL,NULL);
7402 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7405 debug(F100,tn_msg_out,"",0);
7406 if (tn_deb || debses) tn_debug(tn_msg_out);
7408 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7410 ReleaseTelnetMutex();
7415 if (tnc_wait((CHAR *)"comport get datasize",0) < 0) {
7419 debug(F111,"tnc_get_datasize","end",tnc_datasize);
7420 return(tnc_datasize);
7425 tnc_set_parity(int parity)
7426 #else /* CK_ANSIC */
7427 tnc_set_parity(parity) int parity;
7428 #endif /* CK_ANSIC */
7429 /* tnc_set_parity */ {
7430 /* IAC SB COM-PORT SET_PARITY <value(1)> IAC SE */
7438 /* Wait for response. Return new host value. */
7441 debug(F110,"tnc_set_parity","begin",parity);
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 if ( !(parity >= 1 && parity <= 5) )
7457 if ( parity != 0 && parity == tnc_parity )
7460 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7461 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7462 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7463 sb_out[i++] = TNC_C2S_SET_PARITY; /* Set Parity */
7464 sb_out[i++] = (unsigned char)(parity & 0xFF);
7465 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7466 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7469 if (deblog || tn_deb || debses) {
7470 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7471 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7472 " SET-PARITY ", ckitoa(parity)," IAC SE", NULL,
7473 NULL,NULL,NULL,NULL,NULL,NULL);
7477 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7480 debug(F100,tn_msg_out,"",0);
7481 if (tn_deb || debses) tn_debug(tn_msg_out);
7483 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7485 ReleaseTelnetMutex();
7490 if (tnc_wait((CHAR *)"comport set parity",0) < 0) {
7494 debug(F111,"tnc_set_parity","end",tnc_parity);
7500 tnc_get_parity(void)
7501 #else /* CK_ANSIC */
7503 #endif /* CK_ANSIC */
7504 /* tnc_get_parity */ {
7505 /* IAC SB COM-PORT SET_PARITY <value(1)=0> IAC SE */
7506 /* wait for response */
7509 debug(F110,"tnc_get_parity","begin",0);
7510 if (ttnet != NET_TCPB) return(0);
7511 if (ttnproto != NP_TELNET) return(0);
7513 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7516 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7521 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7522 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7523 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7524 sb_out[i++] = TNC_C2S_SET_PARITY; /* Set Parity */
7526 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7527 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7530 if (deblog || tn_deb || debses) {
7531 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7532 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7533 " SET-PARITY ", ckitoa(0)," IAC SE", NULL,
7534 NULL,NULL,NULL,NULL,NULL,NULL);
7538 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7541 debug(F100,tn_msg_out,"",0);
7542 if (tn_deb || debses) tn_debug(tn_msg_out);
7544 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7546 ReleaseTelnetMutex();
7551 if (tnc_wait((CHAR *)"comport get parity",0) < 0) {
7555 debug(F111,"tnc_get_parity","end",tnc_parity);
7561 tnc_set_stopsize(int stopsize)
7562 #else /* CK_ANSIC */
7563 tnc_set_stopsize(stopsize) int stopsize;
7564 #endif /* CK_ANSIC */
7565 /* tnc_set_stopsize */ {
7566 /* IAC SB COM-PORT SET_STOPSIZE <value(1)> IAC SE */
7567 /* Value Stop Bit Size
7572 /* Wait for response. Return new host value. */
7575 debug(F111,"tnc_set_stopsize","begin",stopsize);
7576 if (ttnet != NET_TCPB) return(0);
7577 if (ttnproto != NP_TELNET) return(0);
7579 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7582 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7587 if (!(stopsize >= 1 && stopsize <= 3) )
7590 if ( stopsize != 0 && stopsize == tnc_stopbit )
7591 return(tnc_stopbit);
7593 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7594 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7595 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7596 sb_out[i++] = TNC_C2S_SET_STOPSIZE; /* Set Stop Bits */
7597 sb_out[i++] = (unsigned char)(stopsize & 0xFF);
7598 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7599 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7602 if (deblog || tn_deb || debses) {
7603 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7604 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7605 " SET-STOPSIZE ", ckitoa(stopsize)," IAC SE", NULL,
7606 NULL,NULL,NULL,NULL,NULL,NULL);
7610 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7613 debug(F100,tn_msg_out,"",0);
7614 if (tn_deb || debses) tn_debug(tn_msg_out);
7616 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7618 ReleaseTelnetMutex();
7623 if (tnc_wait((CHAR *)"comport set stopsize",0) < 0) {
7627 debug(F111,"tnc_set_stopsize","end",tnc_stopbit);
7628 return(tnc_stopbit);
7633 tnc_get_stopsize(void)
7634 #else /* CK_ANSIC */
7636 #endif /* CK_ANSIC */
7637 /* tnc_get_stopsize */ {
7638 /* IAC SB COM-PORT SET_STOPSIZE <value(1)=0> IAC SE */
7639 /* Wait for response */
7642 debug(F110,"tnc_get_stopsize","begin",0);
7643 if (ttnet != NET_TCPB) return(0);
7644 if (ttnproto != NP_TELNET) return(0);
7646 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7649 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7654 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7655 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7656 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7657 sb_out[i++] = TNC_C2S_SET_STOPSIZE; /* Set Stop Bits */
7659 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7660 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7663 if (deblog || tn_deb || debses) {
7664 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7665 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7666 " SET-STOPSIZE ", ckitoa(0)," IAC SE", NULL,
7667 NULL,NULL,NULL,NULL,NULL,NULL);
7671 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7674 debug(F100,tn_msg_out,"",0);
7675 if (tn_deb || debses) tn_debug(tn_msg_out);
7677 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7679 ReleaseTelnetMutex();
7684 if (tnc_wait((CHAR *)"comport set stopsize",0) < 0) {
7688 debug(F111,"tnc_get_stopsize","end",tnc_stopbit);
7689 return(tnc_stopbit);
7694 tnc_set_oflow(int control)
7695 #else /* CK_ANSIC */
7696 tnc_set_oflow(control) int control;
7697 #endif /* CK_ANSIC */
7698 /* tnc_set_oflow */ {
7699 /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
7700 /* Value Flow Control
7707 /* wait for response, return new host value. */
7710 debug(F111,"tnc_set_oflow","begin",control);
7711 if (ttnet != NET_TCPB) return(0);
7712 if (ttnproto != NP_TELNET) return(0);
7714 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7717 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7722 if (control != 1 && control != 2 && control != 3 &&
7723 control != 17 && control != 19)
7726 if ( control != 0 && control == tnc_oflow )
7729 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7730 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7731 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7732 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
7733 sb_out[i++] = (unsigned char)(control & 0xFF);
7734 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7735 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7738 if (deblog || tn_deb || debses) {
7739 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7740 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7741 " SET-CONTROL ", ckitoa(control)," IAC SE", NULL,
7742 NULL,NULL,NULL,NULL,NULL,NULL);
7746 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7749 debug(F100,tn_msg_out,"",0);
7750 if (tn_deb || debses) tn_debug(tn_msg_out);
7752 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7754 ReleaseTelnetMutex();
7759 if (tnc_wait((CHAR *)"comport set outbound flow control",0) < 0) {
7763 debug(F111,"tnc_set_oflow","end",tnc_oflow);
7770 #else /* CK_ANSIC */
7772 #endif /* CK_ANSIC */
7773 /* tnc_get_oflow */ {
7774 /* IAC SB COM_PORT SET_CONTROL <value(1)=0> IAC SE */
7775 /* wait for response */
7778 debug(F110,"tnc_get_oflow","begin",0);
7779 if (ttnet != NET_TCPB) return(0);
7780 if (ttnproto != NP_TELNET) return(0);
7782 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7785 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7790 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7791 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7792 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7793 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
7794 sb_out[i++] = TNC_CTL_OFLOW_REQUEST;
7795 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7796 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7799 if (deblog || tn_deb || debses) {
7800 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7801 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7803 ckitoa(TNC_CTL_OFLOW_REQUEST),
7805 NULL,NULL,NULL,NULL,NULL,NULL);
7809 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7812 debug(F100,tn_msg_out,"",0);
7813 if (tn_deb || debses) tn_debug(tn_msg_out);
7815 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7817 ReleaseTelnetMutex();
7822 if (tnc_wait((CHAR *)"comport get outbound flow control",0) < 0) {
7826 debug(F111,"tnc_get_oflow","end",tnc_oflow);
7832 tnc_set_iflow(int control)
7833 #else /* CK_ANSIC */
7834 tnc_set_iflow(control) int control;
7835 #endif /* CK_ANSIC */
7836 /* tnc_set_iflow */ {
7837 /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
7838 /* Value Flow Control
7839 * 14 No Flow Control
7844 /* wait for response, return new host value. */
7847 debug(F111,"tnc_set_iflow","begin",control);
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 if (control != 14 && control != 15 && control != 16 && control != 18)
7862 if ( control != 0 && control == tnc_iflow )
7865 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7866 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7867 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7868 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
7869 sb_out[i++] = (unsigned char)(control & 0xFF);
7870 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7871 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7874 if (deblog || tn_deb || debses) {
7875 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7876 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7877 " SET-CONTROL ", ckitoa(control)," IAC SE", NULL,
7878 NULL,NULL,NULL,NULL,NULL,NULL);
7882 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7885 debug(F100,tn_msg_out,"",0);
7886 if (tn_deb || debses) tn_debug(tn_msg_out);
7888 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7890 ReleaseTelnetMutex();
7895 if (tnc_wait((CHAR *)"comport set inbound flow control",0) < 0) {
7899 debug(F111,"tnc_set_iflow","end",tnc_iflow);
7906 #else /* CK_ANSIC */
7908 #endif /* CK_ANSIC */
7909 /* tnc_get_iflow */ {
7910 /* IAC SB COM_PORT SET_CONTROL <value(1)=13> IAC SE */
7911 /* wait for response */
7914 debug(F110,"tnc_get_iflow","begin",0);
7915 if (ttnet != NET_TCPB) return(0);
7916 if (ttnproto != NP_TELNET) return(0);
7918 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7921 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7926 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7927 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7928 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7929 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
7930 sb_out[i++] = TNC_CTL_IFLOW_REQUEST;
7931 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
7932 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
7935 if (deblog || tn_deb || debses) {
7936 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
7937 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
7939 ckitoa(TNC_CTL_IFLOW_REQUEST),
7941 NULL,NULL,NULL,NULL,NULL,NULL);
7945 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
7948 debug(F100,tn_msg_out,"",0);
7949 if (tn_deb || debses) tn_debug(tn_msg_out);
7951 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
7953 ReleaseTelnetMutex();
7958 if (tnc_wait((CHAR *)"comport get inbound flow control",0) < 0) {
7962 debug(F111,"tnc_get_iflow","end",tnc_iflow);
7968 tnc_set_break_state(int onoff)
7969 #else /* CK_ANSIC */
7970 tnc_set_break_state(onoff) int onoff;
7971 #endif /* CK_ANSIC */
7972 /* tnc_set_break_state */ {
7973 /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
7974 /* Value Break State
7978 /* wait for response, return new host value. */
7981 debug(F111,"tnc_set_break_state","begin",onoff);
7982 if (ttnet != NET_TCPB) return(0);
7983 if (ttnproto != NP_TELNET) return(0);
7985 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
7988 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
7993 if ( onoff != 0 && onoff == tnc_break )
7996 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
7997 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
7998 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
7999 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8000 sb_out[i++] = onoff ?
8001 TNC_CTL_BREAK_ON : TNC_CTL_BREAK_OFF;
8002 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8003 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8006 if (deblog || tn_deb || debses) {
8007 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8008 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8010 onoff ? "BREAK-ON" : "BREAK-OFF",
8012 NULL,NULL,NULL,NULL,NULL,NULL);
8016 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8019 debug(F100,tn_msg_out,"",0);
8020 if (tn_deb || debses) tn_debug(tn_msg_out);
8022 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8024 ReleaseTelnetMutex();
8029 if (tnc_wait((CHAR *)"comport set break state",0) < 0) {
8033 debug(F111,"tnc_set_break_state","end",tnc_break);
8039 tnc_get_break_state(void)
8040 #else /* CK_ANSIC */
8041 tnc_get_break_state()
8042 #endif /* CK_ANSIC */
8043 /* tnc_get_break_state */ {
8044 /* IAC SB COM_PORT SET_CONTROL <value(1)=4> IAC SE */
8045 /* wait for response */
8048 debug(F110,"tnc_get_break_state","begin",0);
8049 if (ttnet != NET_TCPB) return(0);
8050 if (ttnproto != NP_TELNET) return(0);
8052 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8055 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8060 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8061 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8062 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8063 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8064 sb_out[i++] = TNC_CTL_BREAK_REQUEST;
8065 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8066 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8069 if (deblog || tn_deb || debses) {
8070 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8071 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8075 NULL,NULL,NULL,NULL,NULL,NULL);
8079 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8082 debug(F100,tn_msg_out,"",0);
8083 if (tn_deb || debses) tn_debug(tn_msg_out);
8085 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8087 ReleaseTelnetMutex();
8092 if (tnc_wait((CHAR *)"comport get break state",0) < 0) {
8096 debug(F111,"tnc_get_break_state","end",tnc_break);
8102 tnc_set_dtr_state(int onoff)
8103 #else /* CK_ANSIC */
8104 tnc_set_dtr_state(onoff) int onoff;
8105 #endif /* CK_ANSIC */
8106 /* tnc_set_dtr_state */ {
8107 /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
8112 /* wait for response, return new host value. */
8115 debug(F111,"tnc_set_dtr_state","begin",onoff);
8116 if (ttnet != NET_TCPB) return(0);
8117 if (ttnproto != NP_TELNET) return(0);
8119 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8122 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8127 if ( onoff != 0 && onoff == tnc_dtr )
8130 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8131 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8132 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8133 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8134 sb_out[i++] = onoff ?
8135 TNC_CTL_DTR_ON : TNC_CTL_DTR_OFF;
8136 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8137 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8140 if (deblog || tn_deb || debses) {
8141 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8142 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8144 onoff ? "DTR-ON" : "DTR-OFF",
8146 NULL,NULL,NULL,NULL,NULL,NULL);
8150 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8153 debug(F100,tn_msg_out,"",0);
8154 if (tn_deb || debses) tn_debug(tn_msg_out);
8156 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8158 ReleaseTelnetMutex();
8163 if (tnc_wait((CHAR *)"comport set dtr state",0) < 0) {
8167 debug(F111,"tnc_set_dtr_state","end",tnc_dtr);
8173 tnc_get_dtr_state(void)
8174 #else /* CK_ANSIC */
8176 #endif /* CK_ANSIC */
8177 /* tnc_get_dtr_state */ {
8178 /* IAC SB COM_PORT SET_CONTROL <value(1)=7> IAC SE */
8179 /* wait for response */
8182 debug(F110,"tnc_get_dtr_state","begin",0);
8183 if (ttnet != NET_TCPB) return(0);
8184 if (ttnproto != NP_TELNET) return(0);
8186 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8189 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8194 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8195 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8196 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8197 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8198 sb_out[i++] = TNC_CTL_DTR_REQUEST;
8199 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8200 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8203 if (deblog || tn_deb || debses) {
8204 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8205 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8209 NULL,NULL,NULL,NULL,NULL,NULL);
8213 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8216 debug(F100,tn_msg_out,"",0);
8217 if (tn_deb || debses) tn_debug(tn_msg_out);
8219 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8221 ReleaseTelnetMutex();
8226 if (tnc_wait((CHAR *)"comport get dtr state",0) < 0) {
8230 debug(F111,"tnc_get_dtr_state","end",tnc_dtr);
8236 tnc_set_rts_state(int onoff)
8237 #else /* CK_ANSIC */
8238 tnc_set_rts_state(onoff) int onoff;
8239 #endif /* CK_ANSIC */
8240 /* tnc_set_rts_state */ {
8241 /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
8246 /* wait for response, return new host value. */
8249 debug(F111,"tnc_set_rts_state","begin",onoff);
8250 if (ttnet != NET_TCPB) return(0);
8251 if (ttnproto != NP_TELNET) return(0);
8253 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8256 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8261 if ( onoff != 0 && onoff == tnc_rts )
8264 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8265 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8266 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8267 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8268 sb_out[i++] = onoff ?
8269 TNC_CTL_RTS_ON : TNC_CTL_RTS_OFF;
8270 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8271 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8274 if (deblog || tn_deb || debses) {
8275 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8276 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8278 onoff ? "RTS-ON" : "RTS-OFF",
8280 NULL,NULL,NULL,NULL,NULL,NULL);
8284 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8287 debug(F100,tn_msg_out,"",0);
8288 if (tn_deb || debses) tn_debug(tn_msg_out);
8290 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8292 ReleaseTelnetMutex();
8297 if (tnc_wait((CHAR *)"comport set rts state",0) < 0) {
8301 debug(F111,"tnc_set_rts_state","end",tnc_rts);
8307 tnc_get_rts_state(void)
8308 #else /* CK_ANSIC */
8310 #endif /* CK_ANSIC */
8311 /* tnc_get_rts_state */ {
8312 /* IAC SB COM_PORT SET_CONTROL <value(1)=10> IAC SE */
8313 /* wait for response */
8316 debug(F110,"tnc_get_rts_state","begin",0);
8317 if (ttnet != NET_TCPB) return(0);
8318 if (ttnproto != NP_TELNET) return(0);
8320 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8323 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8328 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8329 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8330 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8331 sb_out[i++] = TNC_C2S_SET_CONTROL; /* Set Control */
8332 sb_out[i++] = TNC_CTL_RTS_REQUEST;
8333 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8334 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8337 if (deblog || tn_deb || debses) {
8338 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8339 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8343 NULL,NULL,NULL,NULL,NULL,NULL);
8347 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8350 debug(F100,tn_msg_out,"",0);
8351 if (tn_deb || debses) tn_debug(tn_msg_out);
8353 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8355 ReleaseTelnetMutex();
8360 if (tnc_wait((CHAR *)"comport get rts state",0) < 0) {
8364 debug(F111,"tnc_get_rts_state","end",tnc_rts);
8370 tnc_set_ls_mask(int mask)
8371 #else /* CK_ANSIC */
8372 tnc_set_ls_mask(mask) int mask;
8373 #endif /* CK_ANSIC */
8374 /* tnc_set_ls_mask */ {
8375 /* IAC SB COM_PORT SET_LINESTATE_MASK <value(1)> IAC SE */
8381 * 4 Break Detect Error
8382 * 5 Transfer Holding Register Empty
8383 * 6 Transfer Shift Register Empty
8388 debug(F111,"tnc_set_ls_mask","begin",mask);
8389 if (ttnet != NET_TCPB) return(0);
8390 if (ttnproto != NP_TELNET) return(0);
8392 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8395 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8400 if ( mask != 0 && mask == tnc_ls_mask )
8401 return(tnc_ls_mask);
8403 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8404 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8405 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8406 sb_out[i++] = TNC_C2S_SET_LS_MASK;
8407 sb_out[i++] = (unsigned char)(mask & 0xFF);
8408 if (sb_out[i-1] == IAC )
8410 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8411 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8414 if (deblog || tn_deb || debses) {
8415 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8416 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8417 " SET-LINESTATE-MASK ",
8418 ckitoa(mask & 0xFF),
8420 NULL,NULL,NULL,NULL,NULL,NULL);
8424 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8427 debug(F100,tn_msg_out,"",0);
8428 if (tn_deb || debses) tn_debug(tn_msg_out);
8430 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8432 ReleaseTelnetMutex();
8438 debug(F111,"tnc_set_ls_mask","end",tnc_ls_mask);
8444 tnc_get_ls_mask(void)
8445 #else /* CK_ANSIC */
8447 #endif /* CK_ANSIC */
8448 /* tnc_get_ls_mask */ {
8449 debug(F101,"tnc_get_ls_mask","",tnc_ls_mask);
8450 return(tnc_ls_mask);
8456 #else /* CK_ANSIC */
8458 #endif /* CK_ANSIC */
8461 debug(F101,"tnc_get_ls","",tnc_ls);
8467 tnc_set_ms_mask(int mask)
8468 #else /* CK_ANSIC */
8469 tnc_set_ms_mask(mask) int mask;
8470 #endif /* CK_ANSIC */
8471 /* tnc_set_ms_mask */ {
8472 /* IAC SB COM_PORT SET_MODEMSTATE_MASK <value(1)> IAC SE */
8474 * 0 Delta Clear To Send
8475 * 1 Delta Data Set Ready
8476 * 2 Trailing Edge Ring Detector
8477 * 3 Delta Receive Line Signal (Carrier) Detect
8478 * 4 Clear To Send Signal State
8479 * 5 Data-Set-Ready Signal State
8481 * 7 Receive Line Signal (Carrier) Detect
8486 debug(F111,"tnc_set_ms_mask","begin",mask);
8487 if (ttnet != NET_TCPB) return(0);
8488 if (ttnproto != NP_TELNET) return(0);
8490 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8493 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8498 if ( mask != 0 && mask == tnc_ms_mask )
8499 return(tnc_ms_mask);
8501 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8502 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8503 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8504 sb_out[i++] = TNC_C2S_SET_MS_MASK;
8505 sb_out[i++] = (unsigned char)(mask & 0xFF);
8506 if (sb_out[i-1] == IAC )
8508 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8509 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8512 if (deblog || tn_deb || debses) {
8513 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8514 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8515 " SET-MODEMSTATE-MASK ",
8516 ckitoa(mask & 0xFF),
8518 NULL,NULL,NULL,NULL,NULL,NULL);
8522 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8525 debug(F100,tn_msg_out,"",0);
8526 if (tn_deb || debses) tn_debug(tn_msg_out);
8528 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8530 ReleaseTelnetMutex();
8536 debug(F111,"tnc_set_ms_mask","end",tnc_ms_mask);
8542 tnc_get_ms_mask(void)
8543 #else /* CK_ANSIC */
8545 #endif /* CK_ANSIC */
8546 /* tnc_get_ms_mask */ {
8547 debug(F101,"tnc_get_gs_mask","",tnc_ms_mask);
8548 return(tnc_ms_mask);
8554 #else /* CK_ANSIC */
8556 #endif /* CK_ANSIC */
8559 debug(F101,"tnc_get_ms","",tnc_ms);
8565 tnc_send_purge_data(int mode)
8566 #else /* CK_ANSIC */
8567 tnc_send_purge_data(mode) int mode;
8568 #endif /* CK_ANSIC */
8569 /* tnc_send_purge_data */ {
8570 /* IAC SB COM_PORT PURGE_DATA <value(1)> IAC SE */
8572 * 1 Purge access server receive data buffer
8573 * 2 Purge access server transmit data buffer
8574 * 3 Purge access server receive and transmit data buffers
8579 debug(F111,"tnc_send_purge_data","begin",mode);
8580 if (ttnet != NET_TCPB) return(0);
8581 if (ttnproto != NP_TELNET) return(0);
8583 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8586 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8591 if ( !(mode >= 1 && mode <= 3) )
8594 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8595 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8596 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8597 sb_out[i++] = TNC_C2S_PURGE;
8598 sb_out[i++] = (unsigned char)(mode & 0xFF);
8599 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8600 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8603 if (deblog || tn_deb || debses) {
8604 ckmakxmsg(tn_msg_out,TN_MSG_LEN,
8605 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8607 ckitoa(mode & 0xFF),
8609 NULL,NULL,NULL,NULL,NULL,NULL);
8613 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8616 debug(F100,tn_msg_out,"",0);
8617 if (tn_deb || debses) tn_debug(tn_msg_out);
8619 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8621 ReleaseTelnetMutex();
8625 debug(F110,"tnc_send_purge_data","end",0);
8631 tnc_flow_suspended(void)
8632 #else /* CK_ANSIC */
8633 tnc_flow_suspended()
8634 #endif /* CK_ANSIC */
8635 /* tnc_flow_suspended */ {
8636 debug(F111,"tnc_flow_suspended","",tnc_suspend_xmit);
8637 return(tnc_suspend_xmit);
8642 tnc_suspend_flow(void)
8643 #else /* CK_ANSIC */
8645 #endif /* CK_ANSIC */
8646 /* tnc_suspend_flow */ {
8647 /* IAC SB COM_PORT FLOWCONTROL_SUSPEND IAC SE */
8650 debug(F110,"tnc_suspend_flow","begin",0);
8651 if (ttnet != NET_TCPB) return(0);
8652 if (ttnproto != NP_TELNET) return(0);
8654 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8657 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8662 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8663 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8664 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8665 sb_out[i++] = TNC_C2S_FLOW_SUSPEND;
8666 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8667 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8670 if (deblog || tn_deb || debses) {
8671 ckmakmsg(tn_msg_out,TN_MSG_LEN,
8672 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8673 " FLOWCONTROL-SUSPEND IAC SE", NULL);
8677 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8680 debug(F100,tn_msg_out,"",0);
8681 if (tn_deb || debses) tn_debug(tn_msg_out);
8683 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8685 ReleaseTelnetMutex();
8689 debug(F110,"tnc_suspend_flow","end",0);
8695 tnc_resume_flow(void)
8696 #else /* CK_ANSIC */
8698 #endif /* CK_ANSIC */
8699 /* tnc_resume_flow */ {
8700 /* IAC SB COM_PORT FLOWCONTROL_RESUME IAC SE */
8703 debug(F110,"tnc_resume_flow","begin",0);
8704 if (ttnet != NET_TCPB) return(0);
8705 if (ttnproto != NP_TELNET) return(0);
8707 if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
8710 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
8715 sb_out[i++] = (CHAR) IAC; /* I Am a Command */
8716 sb_out[i++] = (CHAR) SB; /* Subnegotiation */
8717 sb_out[i++] = TELOPT_COMPORT; /* ComPort */
8718 sb_out[i++] = TNC_C2S_FLOW_RESUME;
8719 sb_out[i++] = (CHAR) IAC; /* End of Subnegotiation */
8720 sb_out[i++] = (CHAR) SE; /* marked by IAC SE */
8723 if (deblog || tn_deb || debses) {
8724 ckmakmsg(tn_msg_out,TN_MSG_LEN,
8725 "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
8726 " FLOWCONTROL-RESUME IAC SE", NULL);
8730 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
8733 debug(F100,tn_msg_out,"",0);
8734 if (tn_deb || debses) tn_debug(tn_msg_out);
8736 rc = (ttol((CHAR *)sb_out,i) < 0); /* Send it. */
8738 ReleaseTelnetMutex();
8742 debug(F110,"tnc_resume_flow","end",0);
8748 tnsetflow(int nflow)
8750 tnsetflow(nflow) int nflow;
8751 #endif /* CK_ANSIC */
8756 debug(F111,"tnsetflow","begin",nflow);
8757 if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
8760 if (TELOPT_ME(TELOPT_COMPORT)) {
8764 TNC_CTL_OFLOW_XON_XOFF
8768 TNC_CTL_IFLOW_XON_XOFF
8773 TNC_CTL_OFLOW_RTS_CTS
8777 TNC_CTL_IFLOW_RTS_CTS
8781 /* leave things exactly as they are */
8785 case FLO_DIAL: /* dialing hack */
8786 case FLO_DIAX: /* cancel dialing hack */
8805 debug(F111,"tnsetflow","end",rc);
8806 return(rc >= 0 ? 0 : -1);
8811 tnsettings(int par, int stop)
8813 tnsettings(par, stop) int par, stop;
8814 #endif /* CK_ANSIC */
8818 extern int hwparity;
8820 debug(F111,"tnsettings begin","par",par);
8821 debug(F111,"tnsettings begin","stop",stop);
8822 if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
8825 datasize = par ? TNC_DS_7 : TNC_DS_8;
8826 if (!par) par = hwparity;
8828 if (TELOPT_ME(TELOPT_COMPORT)) {
8831 rc = tnc_set_parity(TNC_PAR_EVEN);
8833 rc = tnc_set_datasize(datasize);
8836 rc = tnc_set_parity(TNC_PAR_ODD);
8838 rc = tnc_set_datasize(datasize);
8841 rc = tnc_set_parity(TNC_PAR_MARK);
8843 rc = tnc_set_datasize(datasize);
8846 rc = tnc_set_parity(TNC_PAR_SPACE);
8848 rc = tnc_set_datasize(datasize);
8852 rc = tnc_set_parity(TNC_PAR_NONE);
8854 rc = tnc_set_datasize(datasize);
8863 rc = tnc_set_stopsize(TNC_SB_2);
8867 rc = tnc_set_stopsize(TNC_SB_1);
8875 debug(F111,"tnsettings","end",rc);
8876 return((rc >= 0) ? 0 : -1);
8879 /* T N G M D M -- Telnet Get modem signals */
8881 Looks for the modem signals CTS, DSR, and CTS, and returns those that are
8882 on in as its return value, in a bit mask as described for ttwmdm.
8885 -2 if the line does not have modem control
8887 >= 0 on success, with a bit mask containing the modem signals that are on.
8894 #endif /* CK_ANSIC */
8899 debug(F110,"tngmdm","begin",0);
8900 if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
8903 if (TELOPT_ME(TELOPT_COMPORT)) {
8904 int modemstate = tnc_get_ms();
8906 if (modemstate & TNC_MS_CTS_SIG)
8908 if (modemstate & TNC_MS_DSR_SIG)
8910 if (modemstate & TNC_MS_RI_SIG)
8912 if (modemstate & TNC_MS_RLSD_SIG)
8914 debug(F111,"tngmdm","end",modem);
8917 debug(F111,"tngmdm","end",-2);
8926 tnsndb(wait) long wait;
8927 #endif /* CK_ANSIC */
8931 debug(F111,"tnsndb","begin",wait);
8932 if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
8935 if (TELOPT_ME(TELOPT_COMPORT)) {
8936 rc = tnc_set_break_state(1);
8938 msleep(wait); /* ZZZzzz */
8939 rc = tnc_set_break_state(0);
8942 debug(F111,"tnsndb","end",rc);
8943 return((rc >= 0) ? 0 : -1);
8945 #endif /* TN_COMPORT */