📄 sshnet.c
字号:
cs->resp = ns; cs->isnew = 1; r->ofcall.count = r->ifcall.count; respond(r, nil);}static voidctlread(Req *r, Client *c){ char buf[32]; sprint(buf, "%d", c->num); readstr(r, buf); respond(r, nil);}static voidctlwrite(Req *r, Client *c){ char *f[3], *s; int nf; Msg *m; s = emalloc(r->ifcall.count+1); memmove(s, r->ifcall.data, r->ifcall.count); s[r->ifcall.count] = '\0'; nf = tokenize(s, f, 3); if(nf == 0){ free(s); respond(r, nil); return; } if(strcmp(f[0], "hangup") == 0){ if(c->state != Established) goto Badarg; if(nf != 1) goto Badarg; queuereq(c, r); teardownclient(c); }else if(strcmp(f[0], "connect") == 0){ if(c->state != Closed) goto Badarg; if(nf != 2) goto Badarg; c->connect = estrdup9p(f[1]); nf = getfields(f[1], f, nelem(f), 0, "!"); if(nf != 2){ free(c->connect); c->connect = nil; goto Badarg; } c->state = Dialing; m = allocmsg(conn, SSH_MSG_PORT_OPEN, 4+4+strlen(f[0])+4+4+strlen("localhost")); putlong(m, c->num); putstring(m, f[0]); putlong(m, ndbfindport(f[1])); putstring(m, "localhost"); queuereq(c, r); sendmsg(m); }else{ Badarg: respond(r, "bad or inappropriate tcp control message"); } free(s);}static voiddataread(Req *r, Client *c){ if(c->state != Established){ respond(r, "not connected"); return; } queuereq(c, r); matchmsgs(c);}static voiddatawrite(Req *r, Client *c){ Msg *m; if(c->state != Established){ respond(r, "not connected"); return; } if(r->ifcall.count){ m = allocmsg(conn, SSH_MSG_CHANNEL_DATA, 4+4+r->ifcall.count); putlong(m, c->servernum); putlong(m, r->ifcall.count); putbytes(m, r->ifcall.data, r->ifcall.count); sendmsg(m); } r->ofcall.count = r->ifcall.count; respond(r, nil);}static voidlocalread(Req *r){ char buf[128]; snprint(buf, sizeof buf, "%s!%d\n", remoteip, 0); readstr(r, buf); respond(r, nil);}static voidremoteread(Req *r, Client *c){ char *s; char buf[128]; s = c->connect; if(s == nil) s = "::!0"; snprint(buf, sizeof buf, "%s\n", s); readstr(r, buf); respond(r, nil);}static voidstatusread(Req *r, Client *c){ char buf[64]; char *s; snprint(buf, sizeof buf, "%s!%d", remoteip, 0); s = statestr[c->state]; readstr(r, s); respond(r, nil);}static voidfsread(Req *r){ char e[ERRMAX]; ulong path; path = r->fid->qid.path; switch(TYPE(path)){ default: snprint(e, sizeof e, "bug in fsread path=%lux", path); respond(r, e); break; case Qroot: dirread9p(r, rootgen, nil); respond(r, nil); break; case Qcs: csread(r); break; case Qtcp: dirread9p(r, tcpgen, nil); respond(r, nil); break; case Qn: dirread9p(r, clientgen, client[NUM(path)]); respond(r, nil); break; case Qctl: ctlread(r, client[NUM(path)]); break; case Qdata: dataread(r, client[NUM(path)]); break; case Qlocal: localread(r); break; case Qremote: remoteread(r, client[NUM(path)]); break; case Qstatus: statusread(r, client[NUM(path)]); break; }}static voidfswrite(Req *r){ ulong path; char e[ERRMAX]; path = r->fid->qid.path; switch(TYPE(path)){ default: snprint(e, sizeof e, "bug in fswrite path=%lux", path); respond(r, e); break; case Qcs: cswrite(r); break; case Qctl: ctlwrite(r, client[NUM(path)]); break; case Qdata: datawrite(r, client[NUM(path)]); break; }}static voidfsopen(Req *r){ static int need[4] = { 4, 2, 6, 1 }; ulong path; int n; Tab *t; Cs *cs; /* * lib9p already handles the blatantly obvious. * we just have to enforce the permissions we have set. */ path = r->fid->qid.path; t = &tab[TYPE(path)]; n = need[r->ifcall.mode&3]; if((n&t->mode) != n){ respond(r, "permission denied"); return; } switch(TYPE(path)){ case Qcs: cs = emalloc(sizeof(Cs)); r->fid->aux = cs; respond(r, nil); break; case Qclone: n = newclient(); path = PATH(Qctl, n); r->fid->qid.path = path; r->ofcall.qid.path = path; if(chatty9p) fprint(2, "open clone => path=%lux\n", path); t = &tab[Qctl]; /* fall through */ default: if(t-tab >= Qn) client[NUM(path)]->ref++; respond(r, nil); break; }}static voidfsflush(Req *r){ int i; for(i=0; i<nclient; i++) if(findreq(client[i], r->oldreq)) respond(r->oldreq, "interrupted"); respond(r, nil);}static voidhandlemsg(Msg *m){ int chan, n; Client *c; switch(m->type){ case SSH_MSG_DISCONNECT: case SSH_CMSG_EXIT_CONFIRMATION: sysfatal("disconnect"); case SSH_CMSG_STDIN_DATA: case SSH_CMSG_EOF: case SSH_CMSG_WINDOW_SIZE: /* don't care */ free(m); break; case SSH_MSG_CHANNEL_DATA: chan = getlong(m); n = getlong(m); if(m->rp+n != m->ep) sysfatal("got bad channel data"); if(chan<nclient && (c=client[chan])->state==Established){ queuemsg(c, m); matchmsgs(c); }else free(m); break; case SSH_MSG_CHANNEL_INPUT_EOF: chan = getlong(m); free(m); if(chan<nclient){ c = client[chan]; chan = c->servernum; hangupclient(c); m = allocmsg(conn, SSH_MSG_CHANNEL_OUTPUT_CLOSED, 4); putlong(m, chan); sendmsg(m); } break; case SSH_MSG_CHANNEL_OUTPUT_CLOSED: chan = getlong(m); if(chan<nclient) hangupclient(client[chan]); free(m); break; case SSH_MSG_CHANNEL_OPEN_CONFIRMATION: chan = getlong(m); c = nil; if(chan>=nclient || (c=client[chan])->state != Dialing){ if(c) fprint(2, "cstate %d\n", c->state); sysfatal("got unexpected open confirmation for %d", chan); } c->servernum = getlong(m); c->state = Established; dialedclient(c); free(m); break; case SSH_MSG_CHANNEL_OPEN_FAILURE: chan = getlong(m); c = nil; if(chan>=nclient || (c=client[chan])->state != Dialing) sysfatal("got unexpected open failure"); if(m->rp+4 <= m->ep) c->servernum = getlong(m); c->state = Closed; dialedclient(c); free(m); break; }}voidfsnetproc(void*){ ulong path; Alt a[4]; Cs *cs; Fid *fid; Req *r; Msg *m; threadsetname("fsthread"); a[0].op = CHANRCV; a[0].c = fsclunkchan; a[0].v = &fid; a[1].op = CHANRCV; a[1].c = fsreqchan; a[1].v = &r; a[2].op = CHANRCV; a[2].c = sshmsgchan; a[2].v = &m; a[3].op = CHANEND; for(;;){ switch(alt(a)){ case 0: path = fid->qid.path; switch(TYPE(path)){ case Qcs: cs = fid->aux; if(cs){ free(cs->resp); free(cs); } break; } if(fid->omode != -1 && TYPE(path) >= Qn) closeclient(client[NUM(path)]); sendp(fsclunkwaitchan, nil); break; case 1: switch(r->ifcall.type){ case Tattach: fsattach(r); break; case Topen: fsopen(r); break; case Tread: fsread(r); break; case Twrite: fswrite(r); break; case Tstat: fsstat(r); break; case Tflush: fsflush(r); break; default: respond(r, "bug in fsthread"); break; } sendp(fsreqwaitchan, 0); break; case 2: handlemsg(m); break; } }}static voidfssend(Req *r){ sendp(fsreqchan, r); recvp(fsreqwaitchan); /* avoids need to deal with spurious flushes */}static voidfsdestroyfid(Fid *fid){ sendp(fsclunkchan, fid); recvp(fsclunkwaitchan);}voidtakedown(Srv*){ threadexitsall("done");}Srv fs = {.attach= fssend,.destroyfid= fsdestroyfid,.walk1= fswalk1,.open= fssend,.read= fssend,.write= fssend,.stat= fssend,.flush= fssend,.end= takedown,};voidthreadmain(int argc, char **argv){ int i, fd; char *host, *user, *p, *service; char *f[16]; Msg *m; static Conn c; fmtinstall('B', mpfmt); fmtinstall('H', encodefmt); mtpt = "/net"; service = nil; user = nil; ARGBEGIN{ case 'B': /* undocumented, debugging */ doabort = 1; break; case 'D': /* undocumented, debugging */ debuglevel = strtol(EARGF(usage()), nil, 0); break; case '9': /* undocumented, debugging */ chatty9p++; break; case 'A': authlist = EARGF(usage()); break; case 'c': cipherlist = EARGF(usage()); break; case 'm': mtpt = EARGF(usage()); break; case 's': service = EARGF(usage()); break; default: usage(); }ARGEND if(argc != 1) usage(); host = argv[0]; if((p = strchr(host, '@')) != nil){ *p++ = '\0'; user = host; host = p; } if(user == nil) user = getenv("user"); if(user == nil) sysfatal("cannot find user name"); privatefactotum(); if((fd = dial(netmkaddr(host, "tcp", "ssh"), nil, nil, nil)) < 0) sysfatal("dialing %s: %r", host); c.interactive = isatty(0); c.fd[0] = c.fd[1] = fd; c.user = user; c.host = host; setaliases(&c, host); c.nokcipher = getfields(cipherlist, f, nelem(f), 1, ", "); c.okcipher = emalloc(sizeof(Cipher*)*c.nokcipher); for(i=0; i<c.nokcipher; i++) c.okcipher[i] = findcipher(f[i], allcipher, nelem(allcipher)); c.nokauth = getfields(authlist, f, nelem(f), 1, ", "); c.okauth = emalloc(sizeof(Auth*)*c.nokauth); for(i=0; i<c.nokauth; i++) c.okauth[i] = findauth(f[i], allauth, nelem(allauth)); sshclienthandshake(&c); requestpty(&c); /* turns on TCP_NODELAY on other side */ m = allocmsg(&c, SSH_CMSG_EXEC_SHELL, 0); sendmsg(m); time0 = time(0); sshmsgchan = chancreate(sizeof(Msg*), 16); fsreqchan = chancreate(sizeof(Req*), 0); fsreqwaitchan = chancreate(sizeof(void*), 0); fsclunkchan = chancreate(sizeof(Fid*), 0); fsclunkwaitchan = chancreate(sizeof(void*), 0); conn = &c; procrfork(sshreadproc, &c, 8192, RFNAMEG|RFNOTEG); procrfork(fsnetproc, nil, 8192, RFNAMEG|RFNOTEG); threadpostmountsrv(&fs, service, mtpt, MREPL); exits(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -