|
|
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.