Print this page
OS-2204 SunSSH has a maximum of 10 multiplexed sessions

@@ -33,10 +33,13 @@
  */
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
+ */
 
 #include "includes.h"
 RCSID("$OpenBSD: session.c,v 1.150 2002/09/16 19:55:33 stevesk Exp $");
 
 #ifdef HAVE_DEFOPEN

@@ -52,10 +55,11 @@
 
 #include "ssh.h"
 #include "ssh1.h"
 #include "ssh2.h"
 #include "xmalloc.h"
+#include "sys-queue.h"
 #include "sshpty.h"
 #include "packet.h"
 #include "buffer.h"
 #include "mpaux.h"
 #include "uidswap.h"

@@ -137,11 +141,13 @@
 /* original command from peer. */
 const char *original_command = NULL;
 
 /* data */
 #define MAX_SESSIONS 10
-Session sessions[MAX_SESSIONS];
+static int sessions_next_id = 0;
+static LIST_HEAD(sessions_head, Session) sessions =
+    LIST_HEAD_INITIALIZER(sessions);
 
 #define SUBSYSTEM_NONE          0
 #define SUBSYSTEM_EXT           1
 #define SUBSYSTEM_INT_SFTP      2
 

@@ -1525,44 +1531,34 @@
 }
 
 Session *
 session_new(void)
 {
-        int i;
-        static int did_init = 0;
-        if (!did_init) {
+        Session *s;
+
                 debug("session_new: init");
-                for (i = 0; i < MAX_SESSIONS; i++) {
-                        sessions[i].used = 0;
-                }
-                did_init = 1;
-        }
-        for (i = 0; i < MAX_SESSIONS; i++) {
-                Session *s = &sessions[i];
-                if (! s->used) {
+
+        s = xmalloc(sizeof (*s));
                         memset(s, 0, sizeof(*s));
                         s->chanid = -1;
                         s->ptyfd = -1;
                         s->ttyfd = -1;
-                        s->used = 1;
-                        s->self = i;
+        s->self = sessions_next_id++;
                         s->env = NULL;
-                        debug("session_new: session %d", i);
-                        return s;
-                }
-        }
-        return NULL;
+        LIST_INSERT_HEAD(&sessions, s, list_entry);
+
+        debug("session_new: session %d", s->self);
+
+        return (s);
 }
 
 static void
 session_dump(void)
 {
-        int i;
-        for (i = 0; i < MAX_SESSIONS; i++) {
-                Session *s = &sessions[i];
-                debug("dump: used %d session %d %p channel %d pid %ld",
-                    s->used,
+        Session *s;
+        LIST_FOREACH(s, &sessions, list_entry) {
+                debug("dump: session %d %p channel %d pid %ld",
                     s->self,
                     s,
                     s->chanid,
                     (long)s->pid);
         }

@@ -1588,15 +1584,14 @@
 
 #ifndef lint
 Session *
 session_by_tty(char *tty)
 {
-        int i;
-        for (i = 0; i < MAX_SESSIONS; i++) {
-                Session *s = &sessions[i];
-                if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
-                        debug("session_by_tty: session %d tty %s", i, tty);
+        Session *s;
+        LIST_FOREACH(s, &sessions, list_entry) {
+                if (s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
+                        debug("session_by_tty: session %d tty %s", s->self, tty);
                         return s;
                 }
         }
         debug("session_by_tty: unknown tty %.100s", tty);
         session_dump();

@@ -1605,15 +1600,14 @@
 #endif /* lint */
 
 static Session *
 session_by_channel(int id)
 {
-        int i;
-        for (i = 0; i < MAX_SESSIONS; i++) {
-                Session *s = &sessions[i];
-                if (s->used && s->chanid == id) {
-                        debug("session_by_channel: session %d channel %d", i, id);
+        Session *s;
+        LIST_FOREACH(s, &sessions, list_entry) {
+                if (s->chanid == id) {
+                        debug("session_by_channel: session %d channel %d", s->self, id);
                         return s;
                 }
         }
         debug("session_by_channel: unknown channel %d", id);
         session_dump();

@@ -1621,15 +1615,14 @@
 }
 
 static Session *
 session_by_pid(pid_t pid)
 {
-        int i;
+        Session *s;
         debug("session_by_pid: pid %ld", (long)pid);
-        for (i = 0; i < MAX_SESSIONS; i++) {
-                Session *s = &sessions[i];
-                if (s->used && s->pid == pid)
+        LIST_FOREACH(s, &sessions, list_entry) {
+                if (s->pid == pid)
                         return s;
         }
         error("session_by_pid: unknown pid %ld", (long)pid);
         session_dump();
         return NULL;

@@ -2285,12 +2278,14 @@
         if (s->auth_proto)
                 xfree(s->auth_proto);
         if (s->command)
                 xfree(s->command);
         session_free_env(&s->env);
-        s->used = 0;
+
+        LIST_REMOVE(s, list_entry);
         session_proctitle(s);
+        xfree(s);
 }
 
 void
 session_close_by_pid(pid_t pid, int status)
 {

@@ -2339,31 +2334,27 @@
 }
 
 void
 session_destroy_all(void (*closefunc)(Session *))
 {
-        int i;
-        for (i = 0; i < MAX_SESSIONS; i++) {
-                Session *s = &sessions[i];
-                if (s->used) {
+        Session *s;
+        LIST_FOREACH(s, &sessions, list_entry) {
                         if (closefunc != NULL)
                                 closefunc(s);
                         else
                                 session_close(s);
                 }
-        }
 }
 
 static char *
 session_tty_list(void)
 {
+        Session *s;
         static char buf[1024];
-        int i;
         buf[0] = '\0';
-        for (i = 0; i < MAX_SESSIONS; i++) {
-                Session *s = &sessions[i];
-                if (s->used && s->ttyfd != -1) {
+        LIST_FOREACH(s, &sessions, list_entry) {
+                if (s->ttyfd != -1) {
                         if (buf[0] != '\0')
                                 strlcat(buf, ",", sizeof buf);
                         strlcat(buf, strrchr(s->tty, '/') + 1, sizeof buf);
                 }
         }