| plan 9 kernel history: overview | file list | diff list |
1995/0804/port/net.c (diff list | history)
| port/net.c on 1991/1107 | ||
| 1991/1107 | #include "u.h" | |
| 1992/0321 | #include "../port/lib.h" | |
| 1991/1107 | #include "mem.h" #include "dat.h" #include "fns.h" | |
| 1992/0111 | #include "../port/error.h" | |
| 1991/1107 | enum { | |
| 1992/0906 | Qlisten = 1, Qclone = 2, Q2nd = 3, Q3rd = 4, Qinf = 5, | |
| 1991/1107 | }; /* | |
| 1992/0623 | * find protection structure */ static Netprot* findprot(Network *np, int id) { Netprot *p; for(p = np->prot; p; p = p->next) if(p->id == id) break; return p; } /* | |
| 1991/1107 | * generate a 3 level directory */ int | |
| 1995/0804 | netgen(Chan *c, void *vp, int, int i, Dir *dp) | |
| 1991/1107 | { Qid q; char buf[32]; Network *np = vp; | |
| 1991/1115 | int t; Netprot *p; int perm; char *o; | |
| 1991/1107 | q.vers = 0; /* top level directory contains the name of the network */ if(c->qid.path == CHDIR){ switch(i){ case 0: q.path = CHDIR | Q2nd; strcpy(buf, np->name); | |
| 1991/1115 | devdir(c, q, buf, 0, eve, 0555, dp); | |
| 1991/1107 | break; default: return -1; } return 1; } /* second level contains clone plus all the conversations */ | |
| 1993/0522 | t = NETTYPE(c->qid.path); | |
| 1991/1115 | if(t == Q2nd || t == Qclone){ | |
| 1991/1107 | if(i == 0){ q.path = Qclone; | |
| 1991/1109 | devdir(c, q, "clone", 0, eve, 0666, dp); | |
| 1991/1114 | }else if(i <= np->nconv){ | |
| 1992/0625 | if(findprot(np, i-1) == 0) return 0; | |
| 1993/0522 | q.path = CHDIR|NETQID(i-1, Q3rd); | |
| 1991/1114 | sprint(buf, "%d", i-1); | |
| 1991/1115 | devdir(c, q, buf, 0, eve, 0555, dp); | |
| 1991/1107 | }else return -1; return 1; } /* third level depends on the number of info files */ | |
| 1993/0522 | p = findprot(np, NETID(c->qid.path)); | |
| 1992/0625 | if(p == 0) return 0; if(*p->owner){ | |
| 1991/1115 | o = p->owner; perm = p->mode; } else { o = eve; perm = 0666; } | |
| 1991/1107 | switch(i){ case 0: | |
| 1993/0522 | q.path = NETQID(NETID(c->qid.path), Ndataqid); | |
| 1991/1115 | devdir(c, q, "data", 0, o, perm, dp); | |
| 1991/1107 | break; case 1: | |
| 1993/0522 | q.path = NETQID(NETID(c->qid.path), Nctlqid); | |
| 1991/1115 | devdir(c, q, "ctl", 0, o, perm, dp); | |
| 1991/1107 | break; case 2: if(np->listen == 0) return 0; | |
| 1993/0522 | q.path = NETQID(NETID(c->qid.path), Qlisten); | |
| 1991/1115 | devdir(c, q, "listen", 0, o, perm, dp); | |
| 1991/1107 | break; default: i -= 3; | |
| 1991/1108 | if(i >= np->ninfo) return -1; | |
| 1993/0522 | q.path = NETQID(NETID(c->qid.path), Qinf+i); | |
| 1991/1115 | devdir(c, q, np->info[i].name, 0, eve, 0444, dp); | |
| 1991/1108 | break; | |
| 1991/1107 | } return 1; } | |
| 1991/1108 | int netwalk(Chan *c, char *name, Network *np) { if(strcmp(name, "..") == 0) { | |
| 1993/0522 | switch(NETTYPE(c->qid.path)){ | |
| 1991/1108 | case Q2nd: c->qid.path = CHDIR; break; case Q3rd: c->qid.path = CHDIR|Q2nd; break; default: panic("netwalk %lux", c->qid.path); } return 1; } return devwalk(c, name, (Dirtab*)np, 0, netgen); } void netstat(Chan *c, char *db, Network *np) { | |
| 1993/0501 | int i; Dir dir; for(i=0;; i++) switch(netgen(c, (Dirtab*)np, 0, i, &dir)){ case -1: /* * devices with interesting directories usually don't get * here, which is good because we've lost the name by now. */ if(c->qid.path & CHDIR){ devdir(c, c->qid, c->path->elem, 0L, eve, CHDIR|0555, &dir); convD2M(&dir, db); return; } print("netstat %C %lux\n", devchar[c->type], c->qid.path); error(Enonexist); case 0: break; case 1: if(eqqid(c->qid, dir.qid)){ if(c->flag&CMSG) dir.mode |= CHMOUNT; convD2M(&dir, db); return; } break; } | |
| 1991/1108 | } | |
| 1991/1107 | Chan * netopen(Chan *c, int omode, Network *np) { | |
| 1991/1122 | int id = 0; | |
| 1992/0623 | Netprot *p; | |
| 1991/1107 | if(c->qid.path & CHDIR){ if(omode != OREAD) error(Eperm); } else { | |
| 1993/0522 | switch(NETTYPE(c->qid.path)){ case Ndataqid: case Nctlqid: id = NETID(c->qid.path); | |
| 1993/0508 | id = (*np->open)(c, id); | |
| 1991/1107 | break; case Qlisten: | |
| 1991/1115 | id = (*np->listen)(c); | |
| 1993/0522 | c->qid.path = NETQID(id, Nctlqid); | |
| 1993/0501 | ptclone(c, 1, id); | |
| 1991/1107 | break; case Qclone: | |
| 1993/0508 | id = (*np->open)(c, -1); | |
| 1993/0522 | c->qid.path = NETQID(id, Nctlqid); | |
| 1993/0501 | ptclone(c, 0, id); | |
| 1991/1107 | break; default: if(omode != OREAD) error(Ebadarg); } | |
| 1993/0522 | switch(NETTYPE(c->qid.path)){ case Ndataqid: case Nctlqid: | |
| 1992/0623 | p = findprot(np, id); | |
| 1993/0501 | if(netown(p, up->user, omode&7) < 0) | |
| 1991/1116 | error(Eperm); | |
| 1991/1107 | break; } } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } long netread(Chan *c, void *a, long n, ulong offset, Network *np) { | |
| 1991/1108 | int t; | |
| 1991/1107 | char buf[256]; if(c->qid.path&CHDIR) return devdirread(c, a, n, (Dirtab*)np, 0, netgen); | |
| 1993/0522 | t = NETTYPE(c->qid.path); if(t == Nctlqid) readnum(offset, a, n, NETID(c->qid.path), NUMSIZE); | |
| 1991/1108 | if(t < Qinf || t >= Qinf + np->ninfo) | |
| 1991/1107 | error(Ebadusefd); | |
| 1991/1108 | (*np->info[t-Qinf].fill)(c, buf, sizeof(buf)); | |
| 1992/0623 | return readstr(offset, a, n, buf); | |
| 1991/1115 | } | |
| 1992/0623 | void netadd(Network *np, Netprot *p, int id) { Netprot **l, *pp; memset(p, 0, sizeof(Netprot)); p->id = id; | |
| 1993/0508 | p->net = np; | |
| 1992/0623 | l = &np->prot; for(pp = np->prot; pp; pp = pp->next){ if(pp->id == id) panic("netadd"); l = &pp->next; } *l = p; } Lock netlock; | |
| 1991/1115 | int | |
| 1992/0623 | netown(Netprot *p, char *o, int omode) | |
| 1991/1115 | { static int access[] = { 0400, 0200, 0600, 0100 }; int mode; int t; | |
| 1992/0623 | lock(&netlock); | |
| 1991/1115 | if(*p->owner){ if(strncmp(o, p->owner, NAMELEN) == 0) /* User */ mode = p->mode; else if(strncmp(o, eve, NAMELEN) == 0) /* Bootes is group */ mode = p->mode<<3; else mode = p->mode<<6; /* Other */ t = access[omode&3]; if((t & mode) == t){ | |
| 1992/0623 | unlock(&netlock); | |
| 1991/1115 | return 0; } else { | |
| 1992/0623 | unlock(&netlock); | |
| 1991/1115 | return -1; } } strncpy(p->owner, o, NAMELEN); | |
| 1992/0623 | p->mode = 0660; unlock(&netlock); | |
| 1991/1115 | return 0; } void | |
| 1992/0623 | netdisown(Netprot *p) | |
| 1991/1115 | { | |
| 1992/0623 | p->owner[0] = 0; | |
| 1992/0819 | } #undef CHDIR /* BUG */ #include "/sys/src/libc/9syscall/sys.h" void netwstat(Chan *c, char *db, Network *np) { Dir dir; Netprot *p; | |
| 1993/0522 | p = findprot(np, NETID(c->qid.path)); | |
| 1992/0819 | if(p == 0) error(Enonexist); lock(np); /* * A network channel's ownership/permissions can be changed only if the * wstat is by the owner or (HACK!) if it is performed using an fwstat. * The latter allows processes started by a network listener to gain * ownership of the connection. The open file descriptor is used as * a capability for the connection. */ | |
| 1993/0501 | if(strncmp(p->owner, up->user, NAMELEN) != 0 && up->scallnr != FWSTAT){ | |
| 1992/0819 | unlock(np); error(Eperm); } convM2D(db, &dir); strncpy(p->owner, dir.uid, NAMELEN); p->mode = dir.mode; unlock(np); | |
| 1991/1107 | } | |