Usermode/telnetd - Option negotation framework, indexed PTY
authorJohn Hodge <[email protected]>
Tue, 7 Jan 2014 05:06:06 +0000 (13:06 +0800)
committerJohn Hodge <[email protected]>
Tue, 7 Jan 2014 05:06:06 +0000 (13:06 +0800)
Usermode/Applications/telnetd_src/main.c

index c7f1978..fa85250 100644 (file)
@@ -13,6 +13,7 @@
 #include <assert.h>
 #include <errno.h>
 #include <acess/devices/pty.h>
+#include <stdbool.h>
 
 // === 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;
+       }
+}
+

UCC git Repository :: git.ucc.asn.au