+ } else if (pktin.type == SSH1_MSG_PORT_OPEN) {
+ /* Remote side is trying to open a channel to talk to a
+ * forwarded port. Give them back a local channel number. */
+ struct ssh_channel *c;
+ struct ssh_rportfwd pf;
+ int hostsize, port;
+ char host[256], buf[1024];
+ char *p, *h, *e;
+ c = smalloc(sizeof(struct ssh_channel));
+
+ hostsize = GET_32BIT(pktin.body+4);
+ for(h = host, p = pktin.body+8; hostsize != 0; hostsize--) {
+ if (h+1 < host+sizeof(host))
+ *h++ = *p;
+ p++;
+ }
+ *h = 0;
+ port = GET_32BIT(p);
+
+ strcpy(pf.dhost, host);
+ pf.dport = port;
+
+ if (find234(ssh_rportfwds, &pf, NULL) == NULL) {
+ sprintf(buf, "Rejected remote port open request for %s:%d",
+ host, port);
+ logevent(buf);
+ send_packet(SSH1_MSG_CHANNEL_OPEN_FAILURE,
+ PKT_INT, GET_32BIT(pktin.body), PKT_END);
+ } else {
+ sprintf(buf, "Received remote port open request for %s:%d",
+ host, port);
+ logevent(buf);
+ e = pfd_newconnect(&c->u.pfd.s, host, port, c);
+ if (e != NULL) {
+ char buf[256];
+ sprintf(buf, "Port open failed: %s", e);
+ logevent(buf);
+ sfree(c);
+ send_packet(SSH1_MSG_CHANNEL_OPEN_FAILURE,
+ PKT_INT, GET_32BIT(pktin.body),
+ PKT_END);
+ } else {
+ c->remoteid = GET_32BIT(pktin.body);
+ c->localid = alloc_channel_id();
+ c->closes = 0;
+ c->v.v1.throttling = 0;
+ c->type = CHAN_SOCKDATA; /* identify channel type */
+ add234(ssh_channels, c);
+ send_packet(SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
+ PKT_INT, c->remoteid, PKT_INT,
+ c->localid, PKT_END);
+ logevent("Forwarded port opened successfully");
+ }
+ }
+
+ } else if (pktin.type == SSH1_MSG_CHANNEL_OPEN_CONFIRMATION) {
+ unsigned int remoteid = GET_32BIT(pktin.body);
+ unsigned int localid = GET_32BIT(pktin.body+4);
+ struct ssh_channel *c;
+
+ c = find234(ssh_channels, &remoteid, ssh_channelfind);
+ if (c && c->type == CHAN_SOCKDATA_DORMANT) {
+ c->remoteid = localid;
+ c->type = CHAN_SOCKDATA;
+ pfd_confirm(c->u.pfd.s);
+ }
+
+ } else if (pktin.type == SSH1_MSG_CHANNEL_OPEN_FAILURE) {
+ unsigned int remoteid = GET_32BIT(pktin.body);
+ unsigned int localid = GET_32BIT(pktin.body+4);
+ struct ssh_channel *c;
+
+ c = find234(ssh_channels, &remoteid, ssh_channelfind);
+ if (c && c->type == CHAN_SOCKDATA_DORMANT) {
+ logevent("Forwarded connection refused by server");
+ pfd_close(c->u.pfd.s);
+ del234(ssh_channels, c);
+ sfree(c);
+ }
+