--- openssh-4.6p1.old/channels.c	2007-01-28 18:16:28.000000000 -0500
+++ openssh-4.6p1/channels.c	2007-08-03 13:15:20.000000000 -0400
@@ -78,11 +78,8 @@
 
 /* -- channel core */
 
-/*
- * Pointer to an array containing all allocated channels.  The array is
- * dynamically extended as needed.
- */
-static Channel **channels = NULL;
+/* test channel code */
+static CNode *head = NULL;
 
 /*
  * Size of the channel array.  All slots of the array must always be
@@ -169,18 +166,20 @@ static void port_open_helper(Channel *c,
 Channel *
 channel_by_id(int id)
 {
-	Channel *c;
-
+	CNode *list;
+	  
 	if (id < 0 || (u_int)id >= channels_alloc) {
 		logit("channel_by_id: %d: bad id", id);
 		return NULL;
 	}
-	c = channels[id];
-	if (c == NULL) {
-		logit("channel_by_id: %d: bad id: channel free", id);
-		return NULL;
+
+	for (list = head; list != NULL; list = list->next) {
+	  if (list->chNum == id) {
+	    return (list->chPtr);
+	  }
 	}
-	return c;
+	logit ("channel_by_id: %d: bad id: channel not found", id);
+	return NULL;
 }
 
 /*
@@ -204,7 +203,7 @@ channel_lookup(int id)
 	case SSH_CHANNEL_OPEN:
 	case SSH_CHANNEL_INPUT_DRAINING:
 	case SSH_CHANNEL_OUTPUT_DRAINING:
-		return (c);
+	  return (c);
 	}
 	logit("Non-public channel %d, type %d.", id, c->type);
 	return (NULL);
@@ -264,39 +263,10 @@ Channel *
 channel_new(char *ctype, int type, int rfd, int wfd, int efd,
     u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock)
 {
-	int found;
-	u_int i;
 	Channel *c;
 
-	/* Do initial allocation if this is the first call. */
-	if (channels_alloc == 0) {
-		channels_alloc = 10;
-		channels = xcalloc(channels_alloc, sizeof(Channel *));
-		for (i = 0; i < channels_alloc; i++)
-			channels[i] = NULL;
-	}
-	/* Try to find a free slot where to put the new channel. */
-	for (found = -1, i = 0; i < channels_alloc; i++)
-		if (channels[i] == NULL) {
-			/* Found a free slot. */
-			found = (int)i;
-			break;
-		}
-	if (found < 0) {
-		/* There are no free slots.  Take last+1 slot and expand the array.  */
-		found = channels_alloc;
-		if (channels_alloc > 10000)
-			fatal("channel_new: internal error: channels_alloc %d "
-			    "too big.", channels_alloc);
-		channels = xrealloc(channels, channels_alloc + 10,
-		    sizeof(Channel *));
-		channels_alloc += 10;
-		debug2("channel: expanding %d", channels_alloc);
-		for (i = found; i < channels_alloc; i++)
-			channels[i] = NULL;
-	}
 	/* Initialize and return new channel. */
-	c = channels[found] = xcalloc(1, sizeof(Channel));
+	c = xcalloc(1, sizeof(Channel));
 	buffer_init(&c->input);
 	buffer_init(&c->output);
 	buffer_init(&c->extended);
@@ -304,11 +274,11 @@ channel_new(char *ctype, int type, int r
 	c->istate = CHAN_INPUT_OPEN;
 	c->flags = 0;
 	channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);
-	c->self = found;
+	c->self = channels_alloc;
 	c->type = type;
 	c->ctype = ctype;
 	c->local_window = window;
-	c->local_window_max = window;
+ 	c->local_window_max = window;
 	c->local_consumed = 0;
 	c->local_maxpacket = maxpack;
 	c->remote_id = -1;
@@ -323,24 +293,24 @@ channel_new(char *ctype, int type, int r
 	c->confirm_ctx = NULL;
 	c->input_filter = NULL;
 	c->output_filter = NULL;
-	debug("channel %d: new [%s]", found, remote_name);
+	debug("channel %d: new [%s]", channels_alloc, remote_name);
+	channel_add_node(&head, c);
+ 	channels_alloc++;
 	return c;
 }
 
 static int
 channel_find_maxfd(void)
 {
-	u_int i;
 	int max = 0;
-	Channel *c;
+ 	Channel *c;
+	CNode *list;
 
-	for (i = 0; i < channels_alloc; i++) {
-		c = channels[i];
-		if (c != NULL) {
-			max = MAX(max, c->rfd);
-			max = MAX(max, c->wfd);
-			max = MAX(max, c->efd);
-		}
+	for (list = head; list != NULL; list = list->next) {
+	  c = list->chPtr;
+	  max = MAX(max, c->rfd);
+	  max = MAX(max, c->wfd);
+	  max = MAX(max, c->efd);
 	}
 	return max;
 }
@@ -367,7 +337,7 @@ channel_close_fds(Channel *c)
 	    c->self, c->rfd, c->wfd, c->efd, c->ctl_fd);
 
 	channel_close_fd(&c->sock);
-	channel_close_fd(&c->ctl_fd);
+ 	channel_close_fd(&c->ctl_fd);
 	channel_close_fd(&c->rfd);
 	channel_close_fd(&c->wfd);
 	channel_close_fd(&c->efd);
@@ -378,11 +348,12 @@ void
 channel_free(Channel *c)
 {
 	char *s;
-	u_int i, n;
-
-	for (n = 0, i = 0; i < channels_alloc; i++)
-		if (channels[i])
-			n++;
+	u_int n;
+	CNode *list;
+	
+	n = 0;
+	for (list = head; list != NULL; list = list->next) 
+	  n++;
 	debug("channel %d: free: %s, nchannels %u", c->self,
 	    c->remote_name ? c->remote_name : "???", n);
 
@@ -400,20 +371,17 @@ channel_free(Channel *c)
 	buffer_free(&c->extended);
 	if (c->remote_name) {
 		xfree(c->remote_name);
-		c->remote_name = NULL;
-	}
-	channels[c->self] = NULL;
+	 	c->remote_name = NULL;
+ 	} 
+	channel_del_node(&head, c);
 	xfree(c);
 }
 
 void
 channel_free_all(void)
 {
-	u_int i;
-
-	for (i = 0; i < channels_alloc; i++)
-		if (channels[i] != NULL)
-			channel_free(channels[i]);
+	while(head)
+	  channel_free(head->chPtr);
 }
 
 /*
@@ -423,11 +391,10 @@ channel_free_all(void)
 void
 channel_close_all(void)
 {
-	u_int i;
+	CNode *list;
 
-	for (i = 0; i < channels_alloc; i++)
-		if (channels[i] != NULL)
-			channel_close_fds(channels[i]);
+	for (list = head; list != NULL; list = list->next)
+	  channel_close_fds(list->chPtr);
 }
 
 /*
@@ -436,22 +403,21 @@ channel_close_all(void)
 void
 channel_stop_listening(void)
 {
-	u_int i;
 	Channel *c;
+	CNode *list;
 
-	for (i = 0; i < channels_alloc; i++) {
-		c = channels[i];
-		if (c != NULL) {
-			switch (c->type) {
-			case SSH_CHANNEL_AUTH_SOCKET:
-			case SSH_CHANNEL_PORT_LISTENER:
-			case SSH_CHANNEL_RPORT_LISTENER:
-			case SSH_CHANNEL_X11_LISTENER:
-				channel_close_fd(&c->sock);
-				channel_free(c);
-				break;
-			}
-		}
+
+	for (list = head; list != NULL; list = list->next) {
+	  c = list->chPtr;
+	  switch (c->type) {
+	  case SSH_CHANNEL_AUTH_SOCKET:
+	  case SSH_CHANNEL_PORT_LISTENER:
+	  case SSH_CHANNEL_RPORT_LISTENER:
+	  case SSH_CHANNEL_X11_LISTENER:
+	    channel_close_fd(&c->sock);
+	    channel_free(c);
+	    break;
+	  }
 	}
 }
 
@@ -462,12 +428,12 @@ channel_stop_listening(void)
 int
 channel_not_very_much_buffered_data(void)
 {
-	u_int i;
 	Channel *c;
+	CNode *list;
 
-	for (i = 0; i < channels_alloc; i++) {
-		c = channels[i];
-		if (c != NULL && c->type == SSH_CHANNEL_OPEN) {
+	for (list = head; list != NULL; list = list->next) {
+	  c = list->chPtr;;
+		if (c->type == SSH_CHANNEL_OPEN) {
 #if 0
 			if (!compat20 &&
 			    buffer_len(&c->input) > packet_get_maxsize()) {
@@ -491,13 +457,11 @@ channel_not_very_much_buffered_data(void
 int
 channel_still_open(void)
 {
-	u_int i;
 	Channel *c;
+	CNode *list;
 
-	for (i = 0; i < channels_alloc; i++) {
-		c = channels[i];
-		if (c == NULL)
-			continue;
+	for (list = head; list != NULL; list = list->next) {
+		c = list->chPtr;
 		switch (c->type) {
 		case SSH_CHANNEL_X11_LISTENER:
 		case SSH_CHANNEL_PORT_LISTENER:
@@ -533,12 +497,12 @@ channel_still_open(void)
 int
 channel_find_open(void)
 {
-	u_int i;
 	Channel *c;
+	CNode *list;
 
-	for (i = 0; i < channels_alloc; i++) {
-		c = channels[i];
-		if (c == NULL || c->remote_id < 0)
+	for (list = head; list != NULL; list = list->next) {
+		c = list->chPtr;
+		if (c->remote_id < 0)
 			continue;
 		switch (c->type) {
 		case SSH_CHANNEL_CLOSED:
@@ -554,12 +518,12 @@ channel_find_open(void)
 		case SSH_CHANNEL_AUTH_SOCKET:
 		case SSH_CHANNEL_OPEN:
 		case SSH_CHANNEL_X11_OPEN:
-			return i;
+			return c->self;
 		case SSH_CHANNEL_INPUT_DRAINING:
 		case SSH_CHANNEL_OUTPUT_DRAINING:
 			if (!compat13)
 				fatal("cannot happen: OUT_DRAIN");
-			return i;
+			return c->self;
 		default:
 			fatal("channel_find_open: bad channel type %d", c->type);
 			/* NOTREACHED */
@@ -580,15 +544,15 @@ channel_open_message(void)
 	Buffer buffer;
 	Channel *c;
 	char buf[1024], *cp;
-	u_int i;
+	CNode *list;
+
 
 	buffer_init(&buffer);
 	snprintf(buf, sizeof buf, "The following connections are open:\r\n");
 	buffer_append(&buffer, buf, strlen(buf));
-	for (i = 0; i < channels_alloc; i++) {
-		c = channels[i];
-		if (c == NULL)
-			continue;
+
+	for (list = head; list != NULL; list = list->next) {
+		c = list->chPtr;
 		switch (c->type) {
 		case SSH_CHANNEL_X11_LISTENER:
 		case SSH_CHANNEL_PORT_LISTENER:
@@ -630,6 +594,7 @@ channel_send_open(int id)
 {
 	Channel *c = channel_lookup(id);
 
+
 	if (c == NULL) {
 		logit("channel_send_open: %d: bad id", id);
 		return;
@@ -648,6 +613,8 @@ channel_request_start(int id, char *serv
 {
 	Channel *c = channel_lookup(id);
 
+
+
 	if (c == NULL) {
 		logit("channel_request_start: %d: unknown channel id", id);
 		return;
@@ -664,6 +631,7 @@ channel_register_confirm(int id, channel
 {
 	Channel *c = channel_lookup(id);
 
+
 	if (c == NULL) {
 		logit("channel_register_comfirm: %d: bad id", id);
 		return;
@@ -712,6 +680,7 @@ channel_register_filter(int id, channel_
 	c->output_filter = ofn;
 }
 
+
 void
 channel_set_fds(int id, int rfd, int wfd, int efd,
     int extusage, int nonblock, u_int window_max)
@@ -1809,19 +1778,18 @@ static void
 channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset)
 {
 	static int did_init = 0;
-	u_int i;
 	Channel *c;
-
+	CNode *list;
+	
 	if (!did_init) {
 		channel_handler_init();
 		did_init = 1;
 	}
-	for (i = 0; i < channels_alloc; i++) {
-		c = channels[i];
-		if (c == NULL)
-			continue;
-		if (ftab[c->type] != NULL)
-			(*ftab[c->type])(c, readset, writeset);
+
+	for (list = head; list != NULL; list = list->next) {
+	  c = list->chPtr;
+	  if (ftab[c->type] != NULL)
+	    (*ftab[c->type])(c, readset, writeset);
 		channel_garbage_collect(c);
 	}
 }
@@ -1874,12 +1842,11 @@ void
 channel_output_poll(void)
 {
 	Channel *c;
-	u_int i, len;
+	u_int len;
+	CNode *list;
 
-	for (i = 0; i < channels_alloc; i++) {
-		c = channels[i];
-		if (c == NULL)
-			continue;
+	for (list = head; list != NULL; list = list->next) {
+    	        c = list->chPtr;
 
 		/*
 		 * We are only interested in channels that can have buffered
@@ -2002,6 +1969,8 @@ channel_input_data(int type, u_int32_t s
 	/* Get the channel number and verify it. */
 	id = packet_get_int();
 	c = channel_lookup(id);
+	
+
 	if (c == NULL)
 		packet_disconnect("Received data for nonexistent channel %d.", id);
 
@@ -2009,7 +1978,6 @@ channel_input_data(int type, u_int32_t s
 	if (c->type != SSH_CHANNEL_OPEN &&
 	    c->type != SSH_CHANNEL_X11_OPEN)
 		return;
-
 	/* Get the data. */
 	data = packet_get_string(&data_len);
 
@@ -2028,7 +1996,6 @@ channel_input_data(int type, u_int32_t s
 		xfree(data);
 		return;
 	}
-
 	if (compat20) {
 		if (data_len > c->local_maxpacket) {
 			logit("channel %d: rcvd big packet %d, maxpack %d",
@@ -2107,6 +2074,7 @@ channel_input_ieof(int type, u_int32_t s
 	id = packet_get_int();
 	packet_check_eom();
 	c = channel_lookup(id);
+
 	if (c == NULL)
 		packet_disconnect("Received ieof for nonexistent channel %d.", id);
 	chan_rcvd_ieof(c);
@@ -2472,16 +2440,17 @@ channel_setup_fwd_listener(int type, con
 int
 channel_cancel_rport_listener(const char *host, u_short port)
 {
-	u_int i;
 	int found = 0;
+	CNode *list;
+	Channel *c;
 
-	for (i = 0; i < channels_alloc; i++) {
-		Channel *c = channels[i];
+	for (list = head; list != NULL; list = list->next) {
+	        c = list->chPtr;
 
-		if (c != NULL && c->type == SSH_CHANNEL_RPORT_LISTENER &&
+		if (c->type == SSH_CHANNEL_RPORT_LISTENER &&
 		    strncmp(c->path, host, sizeof(c->path)) == 0 &&
 		    c->listening_port == port) {
-			debug2("%s: close channel %d", __func__, i);
+			debug2("%s: close channel %d", __func__, c->self);
 			channel_free(c);
 			found = 1;
 		}
@@ -2824,16 +2793,17 @@ channel_connect_to(const char *host, u_s
 void
 channel_send_window_changes(void)
 {
-	u_int i;
 	struct winsize ws;
-
-	for (i = 0; i < channels_alloc; i++) {
-		if (channels[i] == NULL || !channels[i]->client_tty ||
-		    channels[i]->type != SSH_CHANNEL_OPEN)
+	CNode *list;
+	Channel *c;
+	
+	for (list = head; list != NULL; list = list->next) {
+	  c = list->chPtr;
+	  if (!c->client_tty || c->type != SSH_CHANNEL_OPEN)
 			continue;
-		if (ioctl(channels[i]->rfd, TIOCGWINSZ, &ws) < 0)
+		if (ioctl(c->rfd, TIOCGWINSZ, &ws) < 0)
 			continue;
-		channel_request_start(i, "window-change", 0);
+		channel_request_start(c->self, "window-change", 0);
 		packet_put_int((u_int)ws.ws_col);
 		packet_put_int((u_int)ws.ws_row);
 		packet_put_int((u_int)ws.ws_xpixel);
@@ -3234,3 +3204,40 @@ auth_request_forwarding(void)
 	packet_send();
 	packet_write_wait();
 }
+
+
+/* add a node to the linked list of channel pointers */
+/* this is used to determine which channels are or are not */
+/* active.*/
+void channel_add_node (CNode** list, Channel* channel_ptr) {
+  CNode* newnode;
+  newnode = xmalloc(sizeof(CNode));
+
+  newnode->chPtr = channel_ptr;
+  newnode->chNum = channel_ptr->self;
+  newnode->next = *list;
+  *list = newnode;
+  debug("adding   channel %p(%d) to   node %p\n", channel_ptr, channel_ptr->self, newnode);
+  return;
+}
+
+ void channel_del_node (CNode** list, Channel* channel_ptr) {
+  CNode* current;
+  CNode* prev;
+  prev = NULL;
+  
+  for (current = *list; current !=NULL; prev = current, current=current->next) {
+    if (current->chPtr == channel_ptr) {
+      if (prev == NULL) {
+	debug("setting *list = current->next to %p = %p", *list, current->next);
+	*list = current->next;
+      } else {
+	prev->next = current->next;
+      }
+      debug("removing channel %p(%d) from node %p\n",current->chPtr,current->chNum,current);
+      xfree(current);
+    }
+  }  
+  return;
+}
+
