/* * Process IAC DONT <option>. */ static void telnet_dont(telnet_t *tp, u_char opt) { opt_t *op; op = telnet_get_optp(tp, opt); if (op == NULL) return; switch (op->o_us) { case OS_NO: break; case OS_YES: op->o_us = OS_NO; telnet_send_wont(tp, opt); telnet_ack_ldisab(tp, opt); break; case OS_WANTNO: switch (op->o_usq) { case OQ_EMPTY: op->o_us = OS_NO; telnet_ack_ldisab(tp, opt); break; case OQ_OPPOSITE: op->o_us = OS_WANTYES; op->o_usq = OQ_EMPTY; telnet_send_will(tp, opt); break; } break; case OS_WANTYES: switch (op->o_usq) { case OQ_EMPTY: op->o_us = OS_NO; telnet_ack_ldisab(tp, opt); break; case OQ_OPPOSITE: op->o_us = OS_NO; op->o_usq = OQ_EMPTY; telnet_ack_ldisab(tp, opt); break; } break; } }
/* * Negotiate disabling an option in the remote-to-local direction. */ static void telnet_neg_rdisab(telnet_t *tp, u_char opt) { opt_t *op; op = telnet_get_optp(tp, opt); if (op == NULL) return; switch (op->o_him) { case OS_NO: break; case OS_YES: op->o_him = OS_WANTNO; telnet_send_dont(tp, opt); break; case OS_WANTNO: switch (op->o_himq) { case OQ_EMPTY: break; case OQ_OPPOSITE: op->o_himq = OQ_EMPTY; break; } break; case OS_WANTYES: switch (op->o_himq) { case OQ_EMPTY: op->o_himq = OQ_OPPOSITE; break; case OQ_OPPOSITE: break; } break; } }
/* * Process IAC DO <option>. */ static void telnet_do(telnet_t *tp, u_char opt) { opt_t *op; if (opt == TELOPT_TM) { telnet_send_will(tp, opt); return; } op = telnet_get_optp(tp, opt); if (op == NULL) { telnet_send_wont(tp, opt); return; } switch (op->o_us) { case OS_NO: if (telnet_lenabp(tp, opt)) { op->o_us = OS_YES; telnet_send_will(tp, opt); telnet_ack_lenab(tp, opt); } else { telnet_send_wont(tp, opt); } break; case OS_YES: break; case OS_WANTNO: switch (op->o_usq) { case OQ_EMPTY: op->o_us = OS_NO; telnet_ack_ldisab(tp, opt); break; case OQ_OPPOSITE: op->o_us = OS_YES; op->o_usq = OQ_EMPTY; telnet_ack_lenab(tp, opt); break; } break; case OS_WANTYES: switch (op->o_usq) { case OQ_EMPTY: op->o_us = OS_YES; telnet_ack_lenab(tp, opt); break; case OQ_OPPOSITE: op->o_us = OS_WANTNO; op->o_usq = OQ_EMPTY; telnet_send_wont(tp, opt); } break; } }
/* * Process IAC WILL <option>. */ static void telnet_will(telnet_t *tp, u_char opt) { opt_t *op; op = telnet_get_optp(tp, opt); if (op == NULL) { telnet_send_dont(tp, opt); return; } switch (op->o_him) { case OS_NO: if (telnet_renabp(tp, opt)) { op->o_him = OS_YES; telnet_send_do(tp, opt); telnet_ack_renab(tp, opt); } else { telnet_send_dont(tp, opt); } break; case OS_YES: break; case OS_WANTNO: switch (op->o_himq) { case OQ_EMPTY: op->o_him = OS_NO; telnet_ack_rdisab(tp, opt); break; case OQ_OPPOSITE: op->o_him = OS_YES; op->o_himq = OQ_EMPTY; telnet_ack_renab(tp, opt); break; } break; case OS_WANTYES: switch (op->o_himq) { case OQ_EMPTY: op->o_him = OS_YES; telnet_ack_renab(tp, opt); break; case OQ_OPPOSITE: op->o_him = OS_WANTNO; op->o_himq = OQ_EMPTY; telnet_send_dont(tp, opt); } break; } }