*/
#include "includes.h"
-RCSID("$OpenBSD: serverloop.c,v 1.95 2002/01/16 13:17:51 markus Exp $");
+RCSID("$OpenBSD: serverloop.c,v 1.104 2002/09/19 16:03:15 stevesk Exp $");
#include "xmalloc.h"
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "servconf.h"
+#include "canohost.h"
#include "sshpty.h"
#include "channels.h"
#include "compat.h"
int save_errno = errno;
debug("Received SIGCHLD.");
child_terminated = 1;
+#ifndef _UNICOS
mysignal(SIGCHLD, sigchld_handler);
+#endif
notify_parent();
errno = save_errno;
}
tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
tvp = &tv;
}
- if (tvp!=NULL)
- debug3("tvp!=NULL kid %d mili %d", (int) child_terminated,
- max_time_milliseconds);
/* Wait for something to happen, or the timeout to expire. */
ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
if (FD_ISSET(connection_in, readset)) {
len = read(connection_in, buf, sizeof(buf));
if (len == 0) {
- verbose("Connection closed by remote host.");
+ verbose("Connection closed by %.100s",
+ get_remote_ipaddr());
connection_closed = 1;
if (compat20)
return;
fatal_cleanup();
} else if (len < 0) {
if (errno != EINTR && errno != EAGAIN) {
- verbose("Read error from remote host: %.100s", strerror(errno));
+ verbose("Read error from remote host "
+ "%.100s: %.100s",
+ get_remote_ipaddr(), strerror(errno));
fatal_cleanup();
}
} else {
/* We no longer want our SIGCHLD handler to be called. */
mysignal(SIGCHLD, SIG_DFL);
- wait_pid = waitpid(-1, &wait_status, child_terminated ? WNOHANG : 0);
- if (wait_pid == -1)
- packet_disconnect("wait: %.100s", strerror(errno));
- else if (wait_pid != pid)
- error("Strange, wait returned pid %d, expected %d",
- wait_pid, pid);
+ while ((wait_pid = waitpid(-1, &wait_status, 0)) < 0)
+ if (errno != EINTR)
+ packet_disconnect("wait: %.100s", strerror(errno));
+ if (wait_pid != pid)
+ error("Strange, wait returned pid %ld, expected %ld",
+ (long)wait_pid, (long)pid);
/* Check if it exited normally. */
if (WIFEXITED(wait_status)) {
sigaddset(&nset, SIGCHLD);
sigprocmask(SIG_BLOCK, &nset, &oset);
if (child_terminated) {
- while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
- session_close_by_pid(pid, status);
+ while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
+ (pid < 0 && errno == EINTR))
+ if (pid > 0)
+ session_close_by_pid(pid, status);
child_terminated = 0;
}
sigprocmask(SIG_SETMASK, &oset, NULL);
channel_free_all();
/* free remaining sessions, e.g. remove wtmp entries */
- session_destroy_all();
+ session_destroy_all(NULL);
}
static void
c = channel_new(ctype, SSH_CHANNEL_CONNECTING,
sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT,
CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"), 1);
- if (c == NULL) {
- error("server_request_direct_tcpip: channel_new failed");
- close(sock);
- }
return c;
}
c = channel_new(ctype, SSH_CHANNEL_LARVAL,
-1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
0, xstrdup("server-session"), 1);
- if (c == NULL) {
- error("server_request_session: channel_new failed");
- return NULL;
- }
if (session_open(xxx_authctxt, c->self) != 1) {
debug("session open failed, free channel %d", c->self);
channel_free(c);
return NULL;
}
- channel_register_callback(c->self, SSH2_MSG_CHANNEL_REQUEST,
- session_input_channel_req, (void *)0);
channel_register_cleanup(c->self, session_close_by_channel);
return c;
}
{
Channel *c = NULL;
char *ctype;
- u_int len;
int rchan;
- int rmaxpack;
- int rwindow;
+ u_int rmaxpack, rwindow, len;
ctype = packet_get_string(&len);
rchan = packet_get_int();
/* check permissions */
if (!options.allow_tcp_forwarding ||
- no_port_forwarding_flag ||
- (listen_port < IPPORT_RESERVED && pw->pw_uid != 0)) {
+ no_port_forwarding_flag
+#ifndef NO_IPPORT_RESERVED_CONCEPT
+ || (listen_port < IPPORT_RESERVED && pw->pw_uid != 0)
+#endif
+ ) {
success = 0;
packet_send_debug("Server has disabled port forwarding.");
} else {
}
xfree(rtype);
}
+static void
+server_input_channel_req(int type, u_int32_t seq, void *ctxt)
+{
+ Channel *c;
+ int id, reply, success = 0;
+ char *rtype;
+
+ id = packet_get_int();
+ rtype = packet_get_string(NULL);
+ reply = packet_get_char();
+
+ debug("server_input_channel_req: channel %d request %s reply %d",
+ id, rtype, reply);
+
+ if ((c = channel_lookup(id)) == NULL)
+ packet_disconnect("server_input_channel_req: "
+ "unknown channel %d", id);
+ if (c->type == SSH_CHANNEL_LARVAL || c->type == SSH_CHANNEL_OPEN)
+ success = session_input_channel_req(c, rtype);
+ if (reply) {
+ packet_start(success ?
+ SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
+ packet_put_int(c->remote_id);
+ packet_send();
+ }
+ xfree(rtype);
+}
static void
server_init_dispatch_20(void)
dispatch_set(SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open);
dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
- dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
+ dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req);
dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
/* client_alive */