134e04225SDavid du Colombier #include <u.h> 234e04225SDavid du Colombier #include <libc.h> 334e04225SDavid du Colombier #include <thread.h> 434e04225SDavid du Colombier #include <sunrpc.h> 534e04225SDavid du Colombier 634e04225SDavid du Colombier /* 734e04225SDavid du Colombier * Sun RPC server; for now, no reply cache 834e04225SDavid du Colombier */ 934e04225SDavid du Colombier 1034e04225SDavid du Colombier static void sunRpcProc(void*); 1134e04225SDavid du Colombier static void sunRpcRequestThread(void*); 1234e04225SDavid du Colombier static void sunRpcReplyThread(void*); 1334e04225SDavid du Colombier static void sunRpcForkThread(void*); 1434e04225SDavid du Colombier static SunProg *sunFindProg(SunSrv*, SunMsg*, SunRpc*, Channel**); 1534e04225SDavid du Colombier 1634e04225SDavid du Colombier typedef struct Targ Targ; 1734e04225SDavid du Colombier struct Targ 1834e04225SDavid du Colombier { 1934e04225SDavid du Colombier void (*fn)(void*); 2034e04225SDavid du Colombier void *arg; 2134e04225SDavid du Colombier }; 2234e04225SDavid du Colombier 2334e04225SDavid du Colombier SunSrv* 2434e04225SDavid du Colombier sunSrv(void) 2534e04225SDavid du Colombier { 2634e04225SDavid du Colombier SunSrv *srv; 2734e04225SDavid du Colombier 2834e04225SDavid du Colombier srv = emalloc(sizeof(SunSrv)); 2934e04225SDavid du Colombier srv->chatty = 0; 3034e04225SDavid du Colombier srv->crequest = chancreate(sizeof(SunMsg*), 16); 3134e04225SDavid du Colombier srv->creply = chancreate(sizeof(SunMsg*), 16); 3234e04225SDavid du Colombier srv->cthread = chancreate(sizeof(Targ), 4); 3334e04225SDavid du Colombier 3434e04225SDavid du Colombier proccreate(sunRpcProc, srv, SunStackSize); 3534e04225SDavid du Colombier return srv; 3634e04225SDavid du Colombier } 3734e04225SDavid du Colombier 3834e04225SDavid du Colombier void 3934e04225SDavid du Colombier sunSrvProg(SunSrv *srv, SunProg *prog, Channel *c) 4034e04225SDavid du Colombier { 4134e04225SDavid du Colombier if(srv->nprog%16 == 0){ 4234e04225SDavid du Colombier srv->prog = erealloc(srv->prog, (srv->nprog+16)*sizeof(srv->prog[0])); 4334e04225SDavid du Colombier srv->cdispatch = erealloc(srv->cdispatch, (srv->nprog+16)*sizeof(srv->cdispatch[0])); 4434e04225SDavid du Colombier } 4534e04225SDavid du Colombier srv->prog[srv->nprog] = prog; 4634e04225SDavid du Colombier srv->cdispatch[srv->nprog] = c; 4734e04225SDavid du Colombier srv->nprog++; 4834e04225SDavid du Colombier } 4934e04225SDavid du Colombier 5034e04225SDavid du Colombier static void 5134e04225SDavid du Colombier sunRpcProc(void *v) 5234e04225SDavid du Colombier { 5334e04225SDavid du Colombier threadcreate(sunRpcReplyThread, v, SunStackSize); 5434e04225SDavid du Colombier threadcreate(sunRpcRequestThread, v, SunStackSize); 5534e04225SDavid du Colombier threadcreate(sunRpcForkThread, v, SunStackSize); 5634e04225SDavid du Colombier 5734e04225SDavid du Colombier } 5834e04225SDavid du Colombier 5934e04225SDavid du Colombier static void 6034e04225SDavid du Colombier sunRpcForkThread(void *v) 6134e04225SDavid du Colombier { 6234e04225SDavid du Colombier SunSrv *srv = v; 6334e04225SDavid du Colombier Targ t; 6434e04225SDavid du Colombier 6534e04225SDavid du Colombier while(recv(srv->cthread, &t) == 1) 6634e04225SDavid du Colombier threadcreate(t.fn, t.arg, SunStackSize); 6734e04225SDavid du Colombier } 6834e04225SDavid du Colombier 6934e04225SDavid du Colombier void 7034e04225SDavid du Colombier sunSrvThreadCreate(SunSrv *srv, void (*fn)(void*), void *arg) 7134e04225SDavid du Colombier { 7234e04225SDavid du Colombier Targ t; 7334e04225SDavid du Colombier 7434e04225SDavid du Colombier t.fn = fn; 7534e04225SDavid du Colombier t.arg = arg; 7634e04225SDavid du Colombier send(srv->cthread, &t); 7734e04225SDavid du Colombier } 7834e04225SDavid du Colombier 7934e04225SDavid du Colombier static void 8034e04225SDavid du Colombier sunRpcRequestThread(void *v) 8134e04225SDavid du Colombier { 8234e04225SDavid du Colombier uchar *p, *ep; 8334e04225SDavid du Colombier Channel *c; 8434e04225SDavid du Colombier SunSrv *srv = v; 8534e04225SDavid du Colombier SunMsg *m; 8634e04225SDavid du Colombier SunProg *pg; 8734e04225SDavid du Colombier SunStatus ok; 8834e04225SDavid du Colombier 8934e04225SDavid du Colombier while((m = recvp(srv->crequest)) != nil){ 9034e04225SDavid du Colombier /* could look up in cache here? */ 9134e04225SDavid du Colombier 92*6ff5e913SDavid du Colombier if(srv->chatty) fprint(2, "sun msg %p count %d\n", m, m->count); 9334e04225SDavid du Colombier m->srv = srv; 9434e04225SDavid du Colombier p = m->data; 9534e04225SDavid du Colombier ep = p+m->count; 9634e04225SDavid du Colombier if(sunRpcUnpack(p, ep, &p, &m->rpc) < 0){ 97*6ff5e913SDavid du Colombier fprint(2, "in: %.*H unpack failed\n", m->count, m->data); 9834e04225SDavid du Colombier sunMsgDrop(m); 9934e04225SDavid du Colombier continue; 10034e04225SDavid du Colombier } 10134e04225SDavid du Colombier if(srv->chatty) 102*6ff5e913SDavid du Colombier fprint(2, "in: %B\n", &m->rpc); 10334e04225SDavid du Colombier 10434e04225SDavid du Colombier if(srv->alwaysReject){ 10534e04225SDavid du Colombier if(srv->chatty) 106*6ff5e913SDavid du Colombier fprint(2, "\trejecting\n"); 10734e04225SDavid du Colombier sunMsgReplyError(m, SunAuthTooWeak); 10834e04225SDavid du Colombier continue; 10934e04225SDavid du Colombier } 11034e04225SDavid du Colombier 11134e04225SDavid du Colombier if(!m->rpc.iscall){ 11234e04225SDavid du Colombier sunMsgReplyError(m, SunGarbageArgs); 11334e04225SDavid du Colombier continue; 11434e04225SDavid du Colombier } 11534e04225SDavid du Colombier 11634e04225SDavid du Colombier if((pg = sunFindProg(srv, m, &m->rpc, &c)) == nil){ 11734e04225SDavid du Colombier /* sunFindProg sent error */ 11834e04225SDavid du Colombier continue; 11934e04225SDavid du Colombier } 12034e04225SDavid du Colombier 12134e04225SDavid du Colombier p = m->rpc.data; 12234e04225SDavid du Colombier ep = p+m->rpc.ndata; 12334e04225SDavid du Colombier m->call = nil; 12434e04225SDavid du Colombier if((ok = sunCallUnpackAlloc(pg, m->rpc.proc<<1, p, ep, &p, &m->call)) != SunSuccess){ 12534e04225SDavid du Colombier sunMsgReplyError(m, ok); 12634e04225SDavid du Colombier continue; 12734e04225SDavid du Colombier } 12834e04225SDavid du Colombier m->call->rpc = m->rpc; 12934e04225SDavid du Colombier 13034e04225SDavid du Colombier if(srv->chatty) 131*6ff5e913SDavid du Colombier fprint(2, "\t%C\n", m->call); 13234e04225SDavid du Colombier 13334e04225SDavid du Colombier m->pg = pg; 13434e04225SDavid du Colombier sendp(c, m); 13534e04225SDavid du Colombier } 13634e04225SDavid du Colombier } 13734e04225SDavid du Colombier 13834e04225SDavid du Colombier static SunProg* 13934e04225SDavid du Colombier sunFindProg(SunSrv *srv, SunMsg *m, SunRpc *rpc, Channel **pc) 14034e04225SDavid du Colombier { 14134e04225SDavid du Colombier int i, vlo, vhi; 14234e04225SDavid du Colombier SunProg *pg; 14334e04225SDavid du Colombier 14434e04225SDavid du Colombier vlo = 0x7fffffff; 14534e04225SDavid du Colombier vhi = -1; 14634e04225SDavid du Colombier 14734e04225SDavid du Colombier for(i=0; i<srv->nprog; i++){ 14834e04225SDavid du Colombier pg = srv->prog[i]; 14934e04225SDavid du Colombier if(pg->prog != rpc->prog) 15034e04225SDavid du Colombier continue; 15134e04225SDavid du Colombier if(pg->vers == rpc->vers){ 15234e04225SDavid du Colombier *pc = srv->cdispatch[i]; 15334e04225SDavid du Colombier return pg; 15434e04225SDavid du Colombier } 15534e04225SDavid du Colombier /* right program, wrong version: record range */ 15634e04225SDavid du Colombier if(pg->vers < vlo) 15734e04225SDavid du Colombier vlo = pg->vers; 15834e04225SDavid du Colombier if(pg->vers > vhi) 15934e04225SDavid du Colombier vhi = pg->vers; 16034e04225SDavid du Colombier } 16134e04225SDavid du Colombier if(vhi == -1){ 16234e04225SDavid du Colombier if(srv->chatty) 163*6ff5e913SDavid du Colombier fprint(2, "\tprogram %ud unavailable\n", rpc->prog); 16434e04225SDavid du Colombier sunMsgReplyError(m, SunProgUnavail); 16534e04225SDavid du Colombier }else{ 16634e04225SDavid du Colombier /* putting these in rpc is a botch */ 16734e04225SDavid du Colombier rpc->low = vlo; 16834e04225SDavid du Colombier rpc->high = vhi; 16934e04225SDavid du Colombier if(srv->chatty) 170*6ff5e913SDavid du Colombier fprint(2, "\tversion %ud unavailable; have %d-%d\n", rpc->vers, vlo, vhi); 17134e04225SDavid du Colombier sunMsgReplyError(m, SunProgMismatch); 17234e04225SDavid du Colombier } 17334e04225SDavid du Colombier return nil; 17434e04225SDavid du Colombier } 17534e04225SDavid du Colombier 17634e04225SDavid du Colombier static void 17734e04225SDavid du Colombier sunRpcReplyThread(void *v) 17834e04225SDavid du Colombier { 17934e04225SDavid du Colombier SunMsg *m; 18034e04225SDavid du Colombier SunSrv *srv = v; 18134e04225SDavid du Colombier 18234e04225SDavid du Colombier while((m = recvp(srv->creply)) != nil){ 18334e04225SDavid du Colombier /* could record in cache here? */ 18434e04225SDavid du Colombier sendp(m->creply, m); 18534e04225SDavid du Colombier } 18634e04225SDavid du Colombier } 18734e04225SDavid du Colombier 18834e04225SDavid du Colombier int 18934e04225SDavid du Colombier sunMsgReplyError(SunMsg *m, SunStatus error) 19034e04225SDavid du Colombier { 19134e04225SDavid du Colombier uchar *p, *bp, *ep; 19234e04225SDavid du Colombier int n; 19334e04225SDavid du Colombier 19434e04225SDavid du Colombier m->rpc.status = error; 19534e04225SDavid du Colombier m->rpc.iscall = 0; 19634e04225SDavid du Colombier m->rpc.verf.flavor = SunAuthNone; 19734e04225SDavid du Colombier m->rpc.data = nil; 19834e04225SDavid du Colombier m->rpc.ndata = 0; 19934e04225SDavid du Colombier 20034e04225SDavid du Colombier if(m->srv->chatty) 201*6ff5e913SDavid du Colombier fprint(2, "out: %B\n", &m->rpc); 20234e04225SDavid du Colombier 20334e04225SDavid du Colombier n = sunRpcSize(&m->rpc); 20434e04225SDavid du Colombier bp = emalloc(n); 20534e04225SDavid du Colombier ep = bp+n; 20634e04225SDavid du Colombier p = bp; 20734e04225SDavid du Colombier if(sunRpcPack(p, ep, &p, &m->rpc) < 0){ 20834e04225SDavid du Colombier fprint(2, "sunRpcPack failed\n"); 20934e04225SDavid du Colombier sunMsgDrop(m); 21034e04225SDavid du Colombier return 0; 21134e04225SDavid du Colombier } 21234e04225SDavid du Colombier if(p != ep){ 21334e04225SDavid du Colombier fprint(2, "sunMsgReplyError: rpc sizes didn't work out\n"); 21434e04225SDavid du Colombier sunMsgDrop(m); 21534e04225SDavid du Colombier return 0; 21634e04225SDavid du Colombier } 21734e04225SDavid du Colombier free(m->data); 21834e04225SDavid du Colombier m->data = bp; 21934e04225SDavid du Colombier m->count = n; 22034e04225SDavid du Colombier sendp(m->srv->creply, m); 22134e04225SDavid du Colombier return 0; 22234e04225SDavid du Colombier } 22334e04225SDavid du Colombier 22434e04225SDavid du Colombier int 22534e04225SDavid du Colombier sunMsgReply(SunMsg *m, SunCall *c) 22634e04225SDavid du Colombier { 22734e04225SDavid du Colombier int n1, n2; 22834e04225SDavid du Colombier uchar *bp, *p, *ep; 22934e04225SDavid du Colombier 23034e04225SDavid du Colombier c->type = m->call->type+1; 23134e04225SDavid du Colombier c->rpc.iscall = 0; 23234e04225SDavid du Colombier c->rpc.prog = m->rpc.prog; 23334e04225SDavid du Colombier c->rpc.vers = m->rpc.vers; 23434e04225SDavid du Colombier c->rpc.proc = m->rpc.proc; 23534e04225SDavid du Colombier c->rpc.xid = m->rpc.xid; 23634e04225SDavid du Colombier 23734e04225SDavid du Colombier if(m->srv->chatty){ 238*6ff5e913SDavid du Colombier fprint(2, "out: %B\n", &c->rpc); 239*6ff5e913SDavid du Colombier fprint(2, "\t%C\n", c); 24034e04225SDavid du Colombier } 24134e04225SDavid du Colombier 24234e04225SDavid du Colombier n1 = sunRpcSize(&c->rpc); 24334e04225SDavid du Colombier n2 = sunCallSize(m->pg, c); 24434e04225SDavid du Colombier 24534e04225SDavid du Colombier bp = emalloc(n1+n2); 24634e04225SDavid du Colombier ep = bp+n1+n2; 24734e04225SDavid du Colombier p = bp; 24834e04225SDavid du Colombier if(sunRpcPack(p, ep, &p, &c->rpc) != SunSuccess){ 24934e04225SDavid du Colombier fprint(2, "sunRpcPack failed\n"); 25034e04225SDavid du Colombier return sunMsgDrop(m); 25134e04225SDavid du Colombier } 25234e04225SDavid du Colombier if(sunCallPack(m->pg, p, ep, &p, c) != SunSuccess){ 25334e04225SDavid du Colombier fprint(2, "pg->pack failed\n"); 25434e04225SDavid du Colombier return sunMsgDrop(m); 25534e04225SDavid du Colombier } 25634e04225SDavid du Colombier if(p != ep){ 25734e04225SDavid du Colombier fprint(2, "sunMsgReply: sizes didn't work out\n"); 25834e04225SDavid du Colombier return sunMsgDrop(m); 25934e04225SDavid du Colombier } 26034e04225SDavid du Colombier free(m->data); 26134e04225SDavid du Colombier m->data = bp; 26234e04225SDavid du Colombier m->count = n1+n2; 26334e04225SDavid du Colombier 26434e04225SDavid du Colombier sendp(m->srv->creply, m); 26534e04225SDavid du Colombier return 0; 26634e04225SDavid du Colombier } 26734e04225SDavid du Colombier 26834e04225SDavid du Colombier int 26934e04225SDavid du Colombier sunMsgDrop(SunMsg *m) 27034e04225SDavid du Colombier { 27134e04225SDavid du Colombier free(m->data); 27234e04225SDavid du Colombier free(m->call); 27334e04225SDavid du Colombier memset(m, 0xFB, sizeof *m); 27434e04225SDavid du Colombier free(m); 27534e04225SDavid du Colombier return 0; 27634e04225SDavid du Colombier } 27734e04225SDavid du Colombier 278