/* * Process an Urgent Data indication. */ static void telnet_exception(ndesc_t *nd, telnet_t *tp) { tp->t_flags |= TF_SYNCH | TF_URGENT; nq_init(tp->t_canq); nd_disable(nd, ND_X); }
static void telnet_read(ndesc_t *nd, telnet_t *tp) { telnet_readbytes(nd, tp); telnet_input(tp); if (tp->t_flags & (TF_INPUT|TF_DISCONNECT)) { if (!tp->task) tp->task = create_task(telnet_interactive, tp); nd_disable(tp->t_nd, ND_R); } }
/* * Read an UPD datagram */ static void udpsvc_read(ndesc_t *nd, udpsvc_t *svc) { int addrlen, cc; struct sockaddr_in addr; struct gdexception exception_frame; if (read_datagram(svc)) { nd_disable(udpsvc_nd, ND_R); svc->task = create_task(udpsvc_process); } }
/* * Read data from the Telnet session to the raw input queue. */ static void telnet_read(ndesc_t *nd, telnet_t *tp) { int cc; if (!nq_full(tp->t_rawq)) { if (tp->t_flags & TF_URGENT) { if (at_mark(nd_fd(nd))) { tp->t_flags &= ~TF_URGENT; nd_enable(nd, ND_X); } } cc = nq_recv(tp->t_rawq, nd_fd(nd), &tp->t_rblen); if (cc == -1) { switch (errno) { case EWOULDBLOCK: case EINTR: case EPROTO: break; default: telnet_disconnect(tp); return; } } if (cc == 0) { telnet_disconnect(tp); return; } if ((tp->t_flags & TF_FLOWC) == 0) nd_enable(nd, ND_C); telnet_enabr(tp); if (!nq_full(tp->t_rawq)) return; } tp->t_flags |= TF_ENABR; nd_disable(nd, ND_R); }
/* * Write data from the output queue to the Telnet session. */ static void telnet_write(ndesc_t *nd, telnet_t *tp) { if (!nq_empty(tp->t_outq)) { if (nq_send(tp->t_outq, nd_fd(nd), &tp->t_sblen) == -1) { switch (errno) { case EWOULDBLOCK: case EINTR: case EPROTO: break; default: telnet_disconnect(tp); return; } } } if (tp->t_flags & TF_OVFLOUTQ) { if (nq_len(tp->t_outq) < TELNET_OUTQ_LOWAT) { tp->t_flags &= ~TF_OVFLOUTQ; nq_puts(tp->t_outq, (u_char *)"*** Truncated. ***\r\n"); } } if (tp->t_flags & TF_FLOWC) { if (nq_len(tp->t_outq) < TELNET_OUTQ_HIWAT) { tp->t_flags &= ~TF_FLOWC; nd_enable(nd, ND_C); } } if (!nq_empty(tp->t_outq)) return; nq_init(tp->t_outq); tp->t_flags |= TF_ENABW; nd_disable(nd, ND_W); }
/* * Write data from the output queue to the Telnet session. */ static void telnet_write(ndesc_t *nd, telnet_t *tp) { if (!nq_empty(tp->t_outq)) { if (nq_send(tp->t_outq, nd_fd(nd), &tp->t_sblen) == -1) { switch (errno) { case EWOULDBLOCK: case EINTR: case EPROTO: break; default: telnet_disconnect(tp); return; } } } if (tp->t_flags & TF_OVFLOUTQ) { if (nq_len(tp->t_outq) < TELNET_OUTQ_LOWAT) { tp->t_flags &= ~TF_OVFLOUTQ; if (tp->t_flags & (TF_INPUT|TF_DISCONNECT) && !tp->task) /* Reenable command processing */ tp->task = create_task(telnet_interactive, tp); } } if (!nq_empty(tp->t_outq)) return; nq_init(tp->t_outq); nd_disable(nd, ND_W); }
static void telnet_ready(ndesc_t *nd, void *vp) { nd_disable(nd, ND_R); create_task(telnet_accept, nd); }
/* * Perform Telnet protocol processing, copying the contents of the raw input * queue to the canonical queue. */ static void telnet_input(ndesc_t *nd, telnet_t *tp) { u_char c; while (!nq_empty(tp->t_rawq)) { if (nq_avail(tp->t_outq) < TELNET_OUTQ_REQUIRED) { tp->t_flags |= TF_FLOWC; nd_disable(nd, ND_C); return; } c = nq_getc(tp->t_rawq); switch (tp->t_state) { case TS_DATA: switch (c) { case NUL: break; case BS: telnet_ec(tp); break; case LF: telnet_eol(tp); return; case CR: tp->t_state = TS_CR; break; case DEL: telnet_ec(tp); break; case IAC: tp->t_state = TS_IAC; break; default: telnet_canq_putc(tp, c); break; } break; case TS_CR: telnet_eol(tp); tp->t_state = TS_DATA; return; case TS_IAC: tp->t_state = TS_DATA; switch (c) { case DM: telnet_dm(tp); break; case AYT: telnet_ayt(nd, tp); break; case EC: telnet_ec(tp); break; case EL: telnet_el(tp); break; case SB: tp->t_state = TS_IAC_SB; break; case WILL: tp->t_state = TS_IAC_WILL; break; case WONT: tp->t_state = TS_IAC_WONT; break; case DO: tp->t_state = TS_IAC_DO; break; case DONT: tp->t_state = TS_IAC_DONT; break; case IAC: telnet_canq_putc(tp, c); break; } break; case TS_IAC_SB: telnet_sb(tp, c); tp->t_state = TS_IAC_SB_DATA; break; case TS_IAC_SB_DATA: switch (c) { case IAC: tp->t_state = TS_IAC_SB_IAC; break; default: telnet_optq_putc(tp, c); break; } break; case TS_IAC_SB_IAC: tp->t_state = TS_IAC_SB_DATA; switch (c) { case SE: telnet_se(tp); tp->t_state = TS_DATA; break; case IAC: telnet_optq_putc(tp, c); break; } break; case TS_IAC_WILL: telnet_will(tp, c); tp->t_state = TS_DATA; break; case TS_IAC_WONT: telnet_wont(tp, c); tp->t_state = TS_DATA; break; case TS_IAC_DO: telnet_do(tp, c); tp->t_state = TS_DATA; break; case TS_IAC_DONT: telnet_dont(tp, c); tp->t_state = TS_DATA; break; } } if ((tp->t_flags & (TF_SGA | TF_GA)) == 0) { if (nq_avail(tp->t_outq) >= 2) { tp->t_flags |= TF_GA; telnet_send_ga(tp); } } nq_init(tp->t_rawq); telnet_enabr(tp); nd_disable(nd, ND_C); }