sshnet: pass on open failure error message, simplify
return the error message from MSG_CHANNEL_OPEN_FAILURE in the "connect" control write. use a extra state "Finished" to distinguish server from client initiated teardown. that way we do not need to track if we send the MSG_CHANNEL_CLOSE message in closeclient(). this way we also cannot be fooled by misbehaving server. simplify hangupclient() by removing state transitions and doing them in the caller explicitely. that way we can use hangupclient() instead of dialedclient().
This commit is contained in:
parent
a278545e3c
commit
2251ef7a32
1 changed files with 40 additions and 41 deletions
|
@ -46,6 +46,7 @@ enum
|
||||||
Dialing,
|
Dialing,
|
||||||
Established,
|
Established,
|
||||||
Teardown,
|
Teardown,
|
||||||
|
Finished,
|
||||||
};
|
};
|
||||||
|
|
||||||
char *statestr[] = {
|
char *statestr[] = {
|
||||||
|
@ -53,6 +54,7 @@ char *statestr[] = {
|
||||||
"Dialing",
|
"Dialing",
|
||||||
"Established",
|
"Established",
|
||||||
"Teardown",
|
"Teardown",
|
||||||
|
"Finished",
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Client
|
struct Client
|
||||||
|
@ -61,7 +63,6 @@ struct Client
|
||||||
int state;
|
int state;
|
||||||
int num;
|
int num;
|
||||||
int servernum;
|
int servernum;
|
||||||
int sentclose;
|
|
||||||
char *connect;
|
char *connect;
|
||||||
|
|
||||||
int sendpkt;
|
int sendpkt;
|
||||||
|
@ -120,7 +121,6 @@ char *mtpt;
|
||||||
int sshfd;
|
int sshfd;
|
||||||
int localport;
|
int localport;
|
||||||
char localip[] = "::";
|
char localip[] = "::";
|
||||||
char Ehangup[] = "hangup on network connection";
|
|
||||||
|
|
||||||
int
|
int
|
||||||
vpack(uchar *p, int n, char *fmt, va_list a)
|
vpack(uchar *p, int n, char *fmt, va_list a)
|
||||||
|
@ -434,23 +434,7 @@ findreq(Client *c, Req *r)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dialedclient(Client *c)
|
hangupclient(Client *c, char *err)
|
||||||
{
|
|
||||||
Req *r;
|
|
||||||
|
|
||||||
if(r=c->wq){
|
|
||||||
if(r->aux != nil)
|
|
||||||
sysfatal("more than one outstanding dial request (BUG)");
|
|
||||||
if(c->state == Established)
|
|
||||||
respond(r, nil);
|
|
||||||
else
|
|
||||||
respond(r, "connect failed");
|
|
||||||
}
|
|
||||||
c->wq = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
hangupclient(Client *c)
|
|
||||||
{
|
{
|
||||||
Req *r;
|
Req *r;
|
||||||
|
|
||||||
|
@ -460,22 +444,17 @@ hangupclient(Client *c)
|
||||||
while((r = c->wq) != nil){
|
while((r = c->wq) != nil){
|
||||||
c->wq = r->aux;
|
c->wq = r->aux;
|
||||||
r->aux = nil;
|
r->aux = nil;
|
||||||
respond(r, Ehangup);
|
respond(r, err);
|
||||||
}
|
}
|
||||||
if(c->state == Established){
|
matchrmsgs(c);
|
||||||
c->state = Teardown;
|
|
||||||
matchrmsgs(c);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
c->state = Closed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
teardownclient(Client *c)
|
teardownclient(Client *c)
|
||||||
{
|
{
|
||||||
hangupclient(c);
|
c->state = Teardown;
|
||||||
if(c->sentclose++ == 0)
|
hangupclient(c, "i/o on hungup channel");
|
||||||
sendmsg(pack(nil, "bu", MSG_CHANNEL_CLOSE, c->servernum));
|
sendmsg(pack(nil, "bu", MSG_CHANNEL_CLOSE, c->servernum));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -485,14 +464,21 @@ closeclient(Client *c)
|
||||||
|
|
||||||
if(--c->ref)
|
if(--c->ref)
|
||||||
return;
|
return;
|
||||||
if(c->state >= Established)
|
switch(c->state){
|
||||||
|
case Established:
|
||||||
teardownclient(c);
|
teardownclient(c);
|
||||||
|
break;
|
||||||
|
case Finished:
|
||||||
|
c->state = Closed;
|
||||||
|
sendmsg(pack(nil, "bu", MSG_CHANNEL_CLOSE, c->servernum));
|
||||||
|
break;
|
||||||
|
}
|
||||||
while((m = c->mq) != nil){
|
while((m = c->mq) != nil){
|
||||||
c->mq = m->link;
|
c->mq = m->link;
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sshreadproc(void*)
|
sshreadproc(void*)
|
||||||
{
|
{
|
||||||
|
@ -813,9 +799,7 @@ ctlwrite(Req *r, Client *c)
|
||||||
nf = getfields(f[1], f, nelem(f), 0, "!");
|
nf = getfields(f[1], f, nelem(f), 0, "!");
|
||||||
if(nf != 2)
|
if(nf != 2)
|
||||||
goto Badarg;
|
goto Badarg;
|
||||||
c->eof = 0;
|
c->recvwin = WinPackets*MaxPacket;
|
||||||
c->sendwin = MaxPacket;
|
|
||||||
c->recvwin = WinPackets * MaxPacket;
|
|
||||||
c->recvacc = 0;
|
c->recvacc = 0;
|
||||||
c->state = Dialing;
|
c->state = Dialing;
|
||||||
queuewreq(c, r);
|
queuewreq(c, r);
|
||||||
|
@ -1074,8 +1058,17 @@ handlemsg(Msg *m)
|
||||||
if(unpack(m, "_u", &chan) < 0)
|
if(unpack(m, "_u", &chan) < 0)
|
||||||
break;
|
break;
|
||||||
c = getclient(chan);
|
c = getclient(chan);
|
||||||
if(c != nil && c->state >= Established)
|
if(c == nil)
|
||||||
hangupclient(c);
|
break;
|
||||||
|
switch(c->state){
|
||||||
|
case Established:
|
||||||
|
c->state = Finished;
|
||||||
|
hangupclient(c, "connection closed");
|
||||||
|
break;
|
||||||
|
case Teardown:
|
||||||
|
c->state = Closed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MSG_CHANNEL_OPEN_CONFIRMATION:
|
case MSG_CHANNEL_OPEN_CONFIRMATION:
|
||||||
if(unpack(m, "_uuuu", &chan, &n, &win, &pkt) < 0)
|
if(unpack(m, "_uuuu", &chan, &n, &win, &pkt) < 0)
|
||||||
|
@ -1089,25 +1082,31 @@ handlemsg(Msg *m)
|
||||||
break;
|
break;
|
||||||
if(pkt <= 0 || pkt > MaxPacket)
|
if(pkt <= 0 || pkt > MaxPacket)
|
||||||
pkt = MaxPacket;
|
pkt = MaxPacket;
|
||||||
|
c->eof = 0;
|
||||||
c->sendpkt = pkt;
|
c->sendpkt = pkt;
|
||||||
c->sendwin = win;
|
c->sendwin = win;
|
||||||
c->servernum = n;
|
c->servernum = n;
|
||||||
c->sentclose = 0;
|
|
||||||
c->state = Established;
|
c->state = Established;
|
||||||
dialedclient(c);
|
if(c->wq != nil){
|
||||||
|
respond(c->wq, nil);
|
||||||
|
c->wq = nil;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MSG_CHANNEL_OPEN_FAILURE:
|
case MSG_CHANNEL_OPEN_FAILURE:
|
||||||
if(unpack(m, "_u____s", &chan, &s, &n) < 0)
|
if(unpack(m, "_u____s", &chan, &s, &n) < 0)
|
||||||
break;
|
break;
|
||||||
|
s = smprint("%.*s", utfnlen(s, n), s);
|
||||||
if(chan == SESSIONCHAN){
|
if(chan == SESSIONCHAN){
|
||||||
sendp(ssherrchan, smprint("%.*s", utfnlen(s, n), s));
|
sendp(ssherrchan, s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
c = getclient(chan);
|
c = getclient(chan);
|
||||||
if(c == nil || c->state != Dialing)
|
if(c == nil || c->state != Dialing){
|
||||||
|
free(s);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
c->state = Closed;
|
c->state = Closed;
|
||||||
dialedclient(c);
|
hangupclient(c, s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
free(m);
|
free(m);
|
||||||
|
|
Loading…
Reference in a new issue