You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/02/04 22:12:04 UTC

[incubator-nuttx-apps] branch master updated: Improvements for telnet server

This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new bf3e6e2  Improvements for telnet server
bf3e6e2 is described below

commit bf3e6e2367f11bf434af63a1d60a637b29df48e7
Author: Xiang Xiao <xi...@xiaomi.com>
AuthorDate: Tue Feb 4 19:09:22 2020 -0300

    Improvements for telnet server
    
    Author: Xiang Xiao <xi...@xiaomi.com>
    
        Check POLLHUP and POLLERR in telnet poll loop
    
          to handle the remote end close correctly
    
        Send "NVT"(network virtual terminal) as the default if getenv("TERM") return NULL
    
          telnet should trigger the error handling if inet_pton return zero
          since zero mean the string has format error
    
        Don't return 1 in _environ_telnet to avoid trigger the compression
        and remove the redundant TELNET_TELOPT_COMPRESS2 check
    
        Change telnet_error_u to telnet_error_e required by the coding standard
    
        Ensure telnet object get freed before the abnormal exit
---
 include/netutils/telnetc.h    |  6 ++---
 netutils/telnetc/telnetc.c    | 41 ++++++++++++++++----------------
 system/telnet/Make.defs       |  2 +-
 system/telnet/telnet_chatd.c  | 37 +++++++++++++++++++++--------
 system/telnet/telnet_client.c | 54 +++++++++++++++++++++++--------------------
 5 files changed, 81 insertions(+), 59 deletions(-)

diff --git a/include/netutils/telnetc.h b/include/netutils/telnetc.h
index d3f87a9..394d3a6 100644
--- a/include/netutils/telnetc.h
+++ b/include/netutils/telnetc.h
@@ -1,5 +1,5 @@
 /****************************************************************************
- * apps/netutils/telnetc/telnetc.c
+ * apps/include/netutils/telnetc.h
  *
  * Leveraged from libtelnet, https://github.com/seanmiddleditch/libtelnet.
  * Modified and re-released under the BSD license:
@@ -208,7 +208,7 @@ extern "C"
 
 /* Error codes */
 
-enum telnet_error_u
+enum telnet_error_e
 {
   TELNET_EOK = 0,                         /* No error */
   TELNET_EBADVAL,                         /* Invalid parameter, or API misuse */
@@ -284,7 +284,7 @@ union telnet_event_u
     const char *func;                     /* Function the error occured in */
     const char *msg;                      /* Error message string */
     int line;                             /* Line of file error occured on */
-    enum telnet_error_u errcode;          /* Error code */
+    enum telnet_error_e errcode;          /* Error code */
   } error;
 
   /* Command event: for IAC */
diff --git a/netutils/telnetc/telnetc.c b/netutils/telnetc/telnetc.c
index d27e93c..a95c659 100644
--- a/netutils/telnetc/telnetc.c
+++ b/netutils/telnetc/telnetc.c
@@ -197,8 +197,8 @@ static const size_t _buffer_sizes_count = sizeof(_buffer_sizes) /
 
 /* Error generation function */
 
-static enum telnet_error_u _error(struct telnet_s *telnet, unsigned line,
-                                  const char *func, enum telnet_error_u err,
+static enum telnet_error_e _error(struct telnet_s *telnet, unsigned line,
+                                  const char *func, enum telnet_error_e err,
                                   int fatal, const char *fmt, ...)
 {
   union telnet_event_u ev;
@@ -230,7 +230,7 @@ static enum telnet_error_u _error(struct telnet_s *telnet, unsigned line,
  */
 
 #if defined(HAVE_ZLIB)
-enum telnet_error_u _init_zlib(struct telnet_s *telnet, int deflate,
+enum telnet_error_e _init_zlib(struct telnet_s *telnet, int deflate,
                                int err_fatal)
 {
   z_stream *z;
@@ -361,7 +361,7 @@ static inline int _check_telopt(struct telnet_s *telnet,
       return 0;
     }
 
-  /* Loop unti found or end marker (us and him both 0) */
+  /* Loop until found or end marker (us and him both 0) */
 
   for (i = 0; telnet->telopts[i].telopt != -1; ++i)
     {
@@ -441,7 +441,7 @@ static inline void _set_rfc1143(struct telnet_s *telnet, unsigned char telopt,
 
   qtmp = (struct telnet_rfc1143_s *)
            realloc(telnet->q,
-                   sizeof(struct telnet_rfc1143_s) *   (telnet->q_size + 4));
+                   sizeof(struct telnet_rfc1143_s) * (telnet->q_size + 4));
   if (qtmp == 0)
     {
       _error(telnet, __LINE__, __func__, TELNET_ENOMEM, 0,
@@ -713,7 +713,7 @@ static int _environ_telnet(struct telnet_s *telnet, unsigned char type,
 
       ev.type = TELNET_EV_ENVIRON;
       telnet->eh(telnet, &ev, telnet->ud);
-      return 1;
+      return 0;
     }
 
   /* Every second byte must be VAR or USERVAR, if present */
@@ -854,7 +854,7 @@ static int _environ_telnet(struct telnet_s *telnet, unsigned char type,
   /* Clean up */
 
   free(values);
-  return 1;
+  return 0;
 }
 
 /* Process an MSSP subnegotiation buffer */
@@ -1104,21 +1104,17 @@ static int _subnegotiate(struct telnet_s *telnet)
      */
 
     case TELNET_TELOPT_COMPRESS2:
-      if (telnet->sb_telopt == TELNET_TELOPT_COMPRESS2)
+      if (_init_zlib(telnet, 0, 1) != TELNET_EOK)
         {
-          if (_init_zlib(telnet, 0, 1) != TELNET_EOK)
-            {
-              return 0;
-            }
+          return 0;
+        }
 
-          /* Notify app that compression was enabled */
+      /* Notify app that compression was enabled */
 
-          ev.type           = TELNET_EV_COMPRESS;
-          ev.compress.state = 1;
-          telnet->eh(telnet, &ev, telnet->ud);
-          return 1;
-        }
-      return 0;
+      ev.type           = TELNET_EV_COMPRESS;
+      ev.compress.state = 1;
+      telnet->eh(telnet, &ev, telnet->ud);
+      return 1;
 #endif /* HAVE_ZLIB */
 
     /* Specially handled subnegotiation telopt types */
@@ -1248,7 +1244,7 @@ void telnet_free(struct telnet_s *telnet)
 
 /* Push a byte into the telnet buffer */
 
-static enum telnet_error_u _buffer_byte(struct telnet_s *telnet,
+static enum telnet_error_e _buffer_byte(struct telnet_s *telnet,
                                         unsigned char byte)
 {
   char *new_buffer;
@@ -2283,6 +2279,11 @@ void telnet_ttype_is(struct telnet_s *telnet, const char *ttype)
     TELNET_IAC, TELNET_SB, TELNET_TELOPT_TTYPE, TELNET_TTYPE_IS
   };
 
+  if (!ttype)
+    {
+      ttype = "NVT";
+    }
+
   _sendu(telnet, IS, sizeof(IS));
   _send(telnet, ttype, strlen(ttype));
   telnet_finish_sb(telnet);
diff --git a/system/telnet/Make.defs b/system/telnet/Make.defs
index 12fe718..0e0954a 100644
--- a/system/telnet/Make.defs
+++ b/system/telnet/Make.defs
@@ -1,5 +1,5 @@
 ############################################################################
-# apps/system/usbmsc/Make.defs
+# apps/system/telnet/Make.defs
 # Adds selected applications to apps/ build
 #
 #   Copyright (C) 2016 Gregory Nutt. All rights reserved.
diff --git a/system/telnet/telnet_chatd.c b/system/telnet/telnet_chatd.c
index 6d51ead..17c4a7d 100644
--- a/system/telnet/telnet_chatd.c
+++ b/system/telnet/telnet_chatd.c
@@ -107,6 +107,23 @@ static struct user_s g_users[MAX_USERS];
  * Private Functions
  ****************************************************************************/
 
+static void cleanup_exit(void)
+{
+  int i;
+
+  for (i = 0; i != MAX_USERS; ++i)
+    {
+      if (g_users[i].sock != -1)
+        {
+          close(g_users[i].sock);
+          free(g_users[i].name);
+          telnet_free(g_users[i].telnet);
+      }
+    }
+
+  exit(1);
+}
+
 static void linebuffer_push(char *buffer, size_t size, int *linepos,
                             char ch, void (*cb) (const char *line, int overflow,
                                                  void *ud), void *ud)
@@ -180,7 +197,7 @@ static void _send(int sock, const char *buffer, unsigned int size)
           if (errno != EINTR && errno != ECONNRESET)
             {
               fprintf(stderr, "send() failed: %d\n", errno);
-              exit(1);
+              cleanup_exit();
             }
           else
             {
@@ -190,7 +207,7 @@ static void _send(int sock, const char *buffer, unsigned int size)
       else if (ret == 0)
         {
           fprintf(stderr, "send() unexpectedly returned 0\n");
-          exit(1);
+          cleanup_exit();
         }
 
       /* Update pointer and size to see if we've got more to send */
@@ -246,6 +263,7 @@ static void _online(const char *line, int overflow, void *ud)
       _message(user->name, "** HAS QUIT **");
       free(user->name);
       user->name = 0;
+      telnet_free(user->telnet);
       return;
     }
 
@@ -258,7 +276,7 @@ static void _input(struct user_s *user, const char *buffer, unsigned int size)
 {
   unsigned int i;
 
-  for (i = 0; i != size; ++i)
+  for (i = 0; user->sock != -1 && i != size; ++i)
     {
       linebuffer_push(user->linebuf, sizeof(user->linebuf), &user->linepos,
                       (char)buffer[i], _online, user);
@@ -420,12 +438,12 @@ int main(int argc, FAR char *argv[])
       if (ret == -1 && errno != EINTR)
         {
           fprintf(stderr, "poll() failed: %d\n", errno);
-          return 1;
+          cleanup_exit();
         }
 
       /* New connection */
 
-      if (pfd[MAX_USERS].revents & POLLIN)
+      if (pfd[MAX_USERS].revents & (POLLIN | POLLERR | POLLHUP))
         {
           /* Accept the sock */
 
@@ -434,7 +452,7 @@ int main(int argc, FAR char *argv[])
                            &addrlen)) == -1)
             {
               fprintf(stderr, "accept() failed: %d\n", errno);
-              return 1;
+              cleanup_exit();
             }
 
           printf("Connection received.\n");
@@ -478,7 +496,7 @@ int main(int argc, FAR char *argv[])
               continue;
             }
 
-          if (pfd[i].revents & POLLIN)
+          if (pfd[i].revents & (POLLIN | POLLERR | POLLHUP))
             {
               if ((ret = recv(g_users[i].sock, buffer, sizeof(buffer), 0)) > 0)
                 {
@@ -488,6 +506,7 @@ int main(int argc, FAR char *argv[])
                 {
                   printf("Connection closed.\n");
                   close(g_users[i].sock);
+                  g_users[i].sock = -1;
                   if (g_users[i].name != 0)
                     {
                       _message(g_users[i].name, "** HAS DISCONNECTED **");
@@ -496,13 +515,11 @@ int main(int argc, FAR char *argv[])
                     }
 
                   telnet_free(g_users[i].telnet);
-                  g_users[i].sock = -1;
-                  break;
                 }
               else if (errno != EINTR)
                 {
                   fprintf(stderr, "recv(client) failed: %d\n", errno);
-                  exit(1);
+                  cleanup_exit();
                 }
             }
         }
diff --git a/system/telnet/telnet_client.c b/system/telnet/telnet_client.c
index 6f1d354..04c17a7 100644
--- a/system/telnet/telnet_client.c
+++ b/system/telnet/telnet_client.c
@@ -156,14 +156,17 @@ static void telnet_ev_send(int sock, const char *buffer, size_t size)
 
   while (size > 0)
     {
-      if ((ret = send(sock, buffer, size, 0)) == -1)
+      if ((ret = send(sock, buffer, size, 0)) <= 0)
         {
-          fprintf(stderr, "send() failed: %d\n", errno);
-          exit(1);
-        }
-      else if (ret == 0)
-        {
-          fprintf(stderr, "send() unexpectedly returned 0\n");
+          if (ret < 0)
+            {
+              fprintf(stderr, "send() failed: %d\n", errno);
+            }
+          else
+            {
+              fprintf(stderr, "send() unexpectedly returned 0\n");
+            }
+          telnet_free(g_telnet);
           exit(1);
         }
 
@@ -245,6 +248,7 @@ static void _event_handler(struct telnet_s *telnet,
 
     case TELNET_EV_ERROR:
       fprintf(stderr, "ERROR: %s\n", ev->error.msg);
+      telnet_free(g_telnet);
       exit(1);
 
     default:
@@ -264,7 +268,7 @@ static void show_usage(const char *progname, int exitcode)
   fprintf(stderr, "\t\tIPv6 form: xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx\n");
   fprintf(stderr, "\t<port> is the (optional) listening port of the Telnet server.\n");
   fprintf(stderr, "\t\tDefault: %u\n", DEFAULT_PORT);
-  exit(exitcode)  ;
+  exit(exitcode);
 }
 
 /****************************************************************************
@@ -337,7 +341,7 @@ int main(int argc, FAR char *argv[])
   server.ipv6.sin6_port   = htons(portno);
 
   ret = inet_pton(AF_INET6, argv[1], server.ipv6.sin6_addr.s6_addr);
-  if (ret < 0)
+  if (ret <= 0)
 #endif
 #ifdef CONFIG_NET_IPv4
     {
@@ -351,7 +355,7 @@ int main(int argc, FAR char *argv[])
       ret = inet_pton(AF_INET, argv[1], &server.ipv4.sin_addr);
     }
 
-  if (ret < 0)
+  if (ret <= 0)
 #endif
     {
       fprintf(stderr, "ERROR: <server-IP-addr> is invalid\n");
@@ -407,40 +411,40 @@ int main(int argc, FAR char *argv[])
     {
       /* Read from stdin */
 
-      if (pfd[0].revents & POLLIN)
+      if (pfd[0].revents & (POLLIN | POLLERR | POLLHUP))
         {
           ret = std_readline(buffer, sizeof(buffer));
           if (ret > 0)
             {
               send_local_input(buffer, ret);
             }
-          else if (ret == 0)
-            {
-              break;
-            }
           else
             {
-              fprintf(stderr, "recv(server) failed: %d\n", errno);
-              exit(1);
+              if (ret < 0)
+                {
+                  fprintf(stderr, "recv(server) failed: %d\n", errno);
+                  ret = 1;
+                }
+              break;
             }
         }
 
       /* Read from client */
 
-      if (pfd[1].revents & POLLIN)
+      if (pfd[1].revents & (POLLIN | POLLERR | POLLHUP))
         {
           if ((ret = recv(sock, buffer, sizeof(buffer), 0)) > 0)
             {
               telnet_recv(g_telnet, buffer, ret);
             }
-          else if (ret == 0)
-            {
-              break;
-            }
           else
             {
-              fprintf(stderr, "recv(client) failed: %d\n", errno);
-              exit(1);
+              if (ret < 0)
+                {
+                  fprintf(stderr, "recv(client) failed: %d\n", errno);
+                  ret = 1;
+                }
+              break;
             }
         }
     }
@@ -449,5 +453,5 @@ int main(int argc, FAR char *argv[])
 
   telnet_free(g_telnet);
   close(sock);
-  return 0;
+  return ret;
 }