From: John Hodge Date: Tue, 7 Jan 2014 05:06:06 +0000 (+0800) Subject: Usermode/telnetd - Option negotation framework, indexed PTY X-Git-Tag: rel0.15~17 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=4952d09a3e7ca2ce076fafe14953a3bc00668d5c;p=tpg%2Facess2.git Usermode/telnetd - Option negotation framework, indexed PTY --- diff --git a/Usermode/Applications/telnetd_src/main.c b/Usermode/Applications/telnetd_src/main.c index c7f1978c..fa852506 100644 --- a/Usermode/Applications/telnetd_src/main.c +++ b/Usermode/Applications/telnetd_src/main.c @@ -13,6 +13,7 @@ #include #include #include +#include // === TYPES === enum eTelnetMode @@ -22,7 +23,10 @@ enum eTelnetMode MODE_WILL, MODE_WONT, MODE_DO, - MODE_DONT + MODE_DONT, + MODE_SUBNEG_OPTION, + MODE_SUBNEG_DATA, + MODE_SUBNEG_IAC, }; typedef struct sClient @@ -37,6 +41,7 @@ void EventLoop(void); void Server_NewClient(int FD); void HandleServerBoundData(tClient *Client); void HandleClientBoundData(tClient *Client); +void HandleOptionRequest(tClient *Client, int Option, bool Value, bool IsRequest); // === GLOBALS === // --- Configuration --- @@ -94,7 +99,8 @@ void EventLoop(void) } // Select! - _SysSelect( maxfd+1, &fds, NULL, NULL, NULL, 0 ); + int rv = _SysSelect( maxfd+1, &fds, NULL, NULL, NULL, 0 ); + _SysDebug("Select return %i", rv); // Check events if( FD_ISSET(giServerFD, &fds) ) @@ -154,7 +160,7 @@ void Server_NewClient(int FD) } // - Initialise { - _SysIOCtl(clt->pty, PTY_IOCTL_SETID, "telnetd0"); + _SysIOCtl(clt->pty, PTY_IOCTL_SETID, "telnetd#"); struct ptymode mode = {.InputMode = 0, .OutputMode=0}; struct ptydims dims = {.W = 80, .H = 25}; _SysIOCtl(clt->pty, PTY_IOCTL_SETMODE, &mode); @@ -163,7 +169,9 @@ void Server_NewClient(int FD) // TODO: Arguments and envp { - int clientfd = _SysOpen("/Devices/pts/telnetd0", OPENFLAG_READ|OPENFLAG_WRITE); + char pty_path[] = "/Devices/pts/telnetd000"; + _SysIOCtl(clt->pty, PTY_IOCTL_GETID, pty_path+13); + int clientfd = _SysOpen(pty_path, OPENFLAG_READ|OPENFLAG_WRITE); if(clientfd < 0) { perror("Unable to open login PTY"); _SysClose(clt->Socket); @@ -171,9 +179,11 @@ void Server_NewClient(int FD) clt->Socket = 0; return ; } + _SysDebug("Using client PTY %s", pty_path); int fds[3] = {clientfd, clientfd, clientfd}; const char *argv[] = {"login", NULL}; _SysSpawn("/Acess/SBin/login", argv, argv, 3, fds, NULL); + _SysClose(clientfd); } } @@ -181,14 +191,16 @@ void HandleServerBoundData(tClient *Client) { uint8_t buf[BUFSIZ]; size_t len; - + + _SysDebug("Client %p", Client); len = _SysRead(Client->Socket, buf, BUFSIZ); + _SysDebug("%i bytes for %p", len, Client); if( len == 0 ) return ; if( len == -1 ) { return ; } // handle options - int last_flush = 0; + // int last_flush = 0; for( int i = 0; i < len; i ++ ) { switch(Client->Mode) @@ -215,6 +227,8 @@ void HandleServerBoundData(tClient *Client) break; case 250: // Subnegotation _SysDebug("Subnegotiation"); + // TODO: Get option ID, and then cache until 'END SB' (240) + Client->Mode = MODE_SUBNEG_OPTION; break; case 251: // WILL Client->Mode = MODE_WILL; @@ -229,27 +243,57 @@ void HandleServerBoundData(tClient *Client) Client->Mode = MODE_DONT; break; case 255: // Literal 255 - Client->Mode = MODE_DATA; - i --; // hacky! + _SysWrite(Client->pty, buf+i, 1); break; } break; case MODE_WILL: _SysDebug("Option %i WILL", buf[i]); + HandleOptionRequest(Client, buf[i], true, false); Client->Mode = MODE_DATA; break; case MODE_WONT: _SysDebug("Option %i WONT", buf[i]); + HandleOptionRequest(Client, buf[i], false, false); Client->Mode = MODE_DATA; break; case MODE_DO: _SysDebug("Option %i DO", buf[i]); + HandleOptionRequest(Client, buf[i], true, true); Client->Mode = MODE_DATA; break; case MODE_DONT: _SysDebug("Option %i DONT", buf[i]); + HandleOptionRequest(Client, buf[i], false, true); Client->Mode = MODE_DATA; break; + case MODE_SUBNEG_OPTION: + _SysDebug("Option %i subnegotation", buf[i]); + Client->Mode = MODE_SUBNEG_DATA; + break; + case MODE_SUBNEG_IAC: + switch(buf[i]) + { + case 240: // End subnegotation + // TODO: Handle subnegotation data + Client->Mode = MODE_DATA; + break; + case 255: + // TODO: Literal 255 + Client->Mode = MODE_SUBNEG_DATA; + break; + default: + _SysDebug("Unexpected %i in SUBNEG IAC", buf[i]); + Client->Mode = MODE_SUBNEG_DATA; + break; + } + case MODE_SUBNEG_DATA: + if( buf[i] == 255 ) + Client->Mode = MODE_SUBNEG_IAC; + else + ;//_SysWrite(Client->pty, buf+i, 1); + break; + case MODE_DATA: if( buf[i] == 255 ) Client->Mode = MODE_IAC; @@ -270,3 +314,13 @@ void HandleClientBoundData(tClient *Client) _SysWrite(Client->Socket, buf, len); } +void HandleOptionRequest(tClient *Client, int Option, bool Value, bool IsRequest) +{ + switch(Option) + { + default: + _SysDebug("Unknown option %i", Option); + break; + } +} +