|
|
1.1 root 1: #include "u.h"
2: #include "../port/lib.h"
3: #include "mem.h"
4: #include "dat.h"
5: #include "fns.h"
6: #include "../port/error.h"
7:
8: enum
9: {
10: Qlisten = 1,
11: Qclone = 2,
12: Q2nd = 3,
13: Q3rd = 4,
14: Qinf = 5,
15: };
16:
17: /*
18: * find protection structure
19: */
20: static Netprot*
21: findprot(Network *np, int id)
22: {
23: Netprot *p;
24:
25: for(p = np->prot; p; p = p->next)
26: if(p->id == id)
27: break;
28: return p;
29: }
30:
31: /*
32: * generate a 3 level directory
33: */
34: int
35: netgen(Chan *c, void *vp, int ntab, int i, Dir *dp)
36: {
37: Qid q;
38: char buf[32];
39: Network *np = vp;
40: int t;
41: Netprot *p;
42: int perm;
43: char *o;
44:
45: USED(ntab);
46: q.vers = 0;
47:
48: /* top level directory contains the name of the network */
49: if(c->qid.path == CHDIR){
50: switch(i){
51: case 0:
52: q.path = CHDIR | Q2nd;
53: strcpy(buf, np->name);
54: devdir(c, q, buf, 0, eve, 0555, dp);
55: break;
56: default:
57: return -1;
58: }
59: return 1;
60: }
61:
62: /* second level contains clone plus all the conversations */
63: t = STREAMTYPE(c->qid.path);
64: if(t == Q2nd || t == Qclone){
65: if(i == 0){
66: q.path = Qclone;
67: devdir(c, q, "clone", 0, eve, 0666, dp);
68: }else if(i <= np->nconv){
69: if(findprot(np, i-1) == 0)
70: return 0;
71: q.path = CHDIR|STREAMQID(i-1, Q3rd);
72: sprint(buf, "%d", i-1);
73: devdir(c, q, buf, 0, eve, 0555, dp);
74: }else
75: return -1;
76: return 1;
77: }
78:
79: /* third level depends on the number of info files */
80: p = findprot(np, STREAMID(c->qid.path));
81: if(p == 0)
82: return 0;
83: if(*p->owner){
84: o = p->owner;
85: perm = p->mode;
86: } else {
87: o = eve;
88: perm = 0666;
89: }
90: switch(i){
91: case 0:
92: q.path = STREAMQID(STREAMID(c->qid.path), Sdataqid);
93: devdir(c, q, "data", 0, o, perm, dp);
94: break;
95: case 1:
96: q.path = STREAMQID(STREAMID(c->qid.path), Sctlqid);
97: devdir(c, q, "ctl", 0, o, perm, dp);
98: break;
99: case 2:
100: if(np->listen == 0)
101: return 0;
102: q.path = STREAMQID(STREAMID(c->qid.path), Qlisten);
103: devdir(c, q, "listen", 0, o, perm, dp);
104: break;
105: default:
106: i -= 3;
107: if(i >= np->ninfo)
108: return -1;
109: q.path = STREAMQID(STREAMID(c->qid.path), Qinf+i);
110: devdir(c, q, np->info[i].name, 0, eve, 0444, dp);
111: break;
112: }
113: return 1;
114: }
115:
116: int
117: netwalk(Chan *c, char *name, Network *np)
118: {
119: if(strcmp(name, "..") == 0) {
120: switch(STREAMTYPE(c->qid.path)){
121: case Q2nd:
122: c->qid.path = CHDIR;
123: break;
124: case Q3rd:
125: c->qid.path = CHDIR|Q2nd;
126: break;
127: default:
128: panic("netwalk %lux", c->qid.path);
129: }
130: return 1;
131: }
132:
133: return devwalk(c, name, (Dirtab*)np, 0, netgen);
134: }
135:
136: void
137: netstat(Chan *c, char *db, Network *np)
138: {
139: devstat(c, db, (Dirtab*)np, 1, netgen);
140: }
141:
142: Chan *
143: netopen(Chan *c, int omode, Network *np)
144: {
145: int id = 0;
146: Netprot *p;
147:
148: if(c->qid.path & CHDIR){
149: if(omode != OREAD)
150: error(Eperm);
151: } else {
152: switch(STREAMTYPE(c->qid.path)){
153: case Sdataqid:
154: case Sctlqid:
155: id = STREAMID(c->qid.path);
156: break;
157: case Qlisten:
158: streamopen(c, np->devp);
159: id = (*np->listen)(c);
160: streamclose(c);
161: c->qid.path = STREAMQID(id, Sctlqid);
162: break;
163: case Qclone:
164: id = (*np->clone)(c);
165: c->qid.path = STREAMQID(id, Sctlqid);
166: break;
167: default:
168: if(omode != OREAD)
169: error(Ebadarg);
170: }
171: switch(STREAMTYPE(c->qid.path)){
172: case Sdataqid:
173: case Sctlqid:
174: streamopen(c, np->devp);
175: if(np->protop && c->stream->devq->next->info != np->protop)
176: pushq(c->stream, np->protop);
177: p = findprot(np, id);
178: if(netown(p, u->p->user, omode&7) < 0)
179: error(Eperm);
180: break;
181: }
182: }
183: c->mode = openmode(omode);
184: c->flag |= COPEN;
185: c->offset = 0;
186: return c;
187: }
188:
189: long
190: netread(Chan *c, void *a, long n, ulong offset, Network *np)
191: {
192: int t;
193: char buf[256];
194:
195: if(c->stream)
196: return streamread(c, a, n);
197:
198: if(c->qid.path&CHDIR)
199: return devdirread(c, a, n, (Dirtab*)np, 0, netgen);
200:
201: t = STREAMTYPE(c->qid.path);
202: if(t < Qinf || t >= Qinf + np->ninfo)
203: error(Ebadusefd);
204:
205: (*np->info[t-Qinf].fill)(c, buf, sizeof(buf));
206: return readstr(offset, a, n, buf);
207: }
208:
209: void
210: netadd(Network *np, Netprot *p, int id)
211: {
212: Netprot **l, *pp;
213:
214: memset(p, 0, sizeof(Netprot));
215: p->id = id;
216:
217: l = &np->prot;
218: for(pp = np->prot; pp; pp = pp->next){
219: if(pp->id == id)
220: panic("netadd");
221: l = &pp->next;
222: }
223: *l = p;
224: }
225:
226: Lock netlock;
227:
228: int
229: netown(Netprot *p, char *o, int omode)
230: {
231: static int access[] = { 0400, 0200, 0600, 0100 };
232: int mode;
233: int t;
234:
235: lock(&netlock);
236: if(*p->owner){
237: if(strncmp(o, p->owner, NAMELEN) == 0) /* User */
238: mode = p->mode;
239: else if(strncmp(o, eve, NAMELEN) == 0) /* Bootes is group */
240: mode = p->mode<<3;
241: else
242: mode = p->mode<<6; /* Other */
243:
244: t = access[omode&3];
245: if((t & mode) == t){
246: unlock(&netlock);
247: return 0;
248: } else {
249: unlock(&netlock);
250: return -1;
251: }
252: }
253: strncpy(p->owner, o, NAMELEN);
254: p->mode = 0660;
255: unlock(&netlock);
256: return 0;
257: }
258:
259: void
260: netdisown(Netprot *p)
261: {
262: p->owner[0] = 0;
263: }
264:
265: #undef CHDIR /* BUG */
266: #include "/sys/src/libc/9syscall/sys.h"
267:
268: void
269: netwstat(Chan *c, char *db, Network *np)
270: {
271: Dir dir;
272: Netprot *p;
273:
274: p = findprot(np, STREAMID(c->qid.path));
275: if(p == 0)
276: error(Enonexist);
277: lock(np);
278:
279: /*
280: * A network channel's ownership/permissions can be changed only if the
281: * wstat is by the owner or (HACK!) if it is performed using an fwstat.
282: * The latter allows processes started by a network listener to gain
283: * ownership of the connection. The open file descriptor is used as
284: * a capability for the connection.
285: */
286: if(strncmp(p->owner, u->p->user, NAMELEN) != 0 && u->scallnr != FWSTAT){
287: unlock(np);
288: error(Eperm);
289: }
290: convM2D(db, &dir);
291: strncpy(p->owner, dir.uid, NAMELEN);
292: p->mode = dir.mode;
293:
294: unlock(np);
295: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.