2 #include "../port/lib.h"
6 #include "../port/error.h"
11 Qtopdir= 1, /* top level directory */
20 Qprotodir, /* directory for a protocol */
25 Qconvdir, /* directory for a conversation */
37 Masktype= (1<<Logtype)-1,
39 Maskconv= (1<<Logconv)-1,
42 Maskproto= (1<<Logproto)-1,
43 Shiftproto= Logtype + Logconv,
47 #define TYPE(x) ( ((ulong)(x).path) & Masktype )
48 #define CONV(x) ( (((ulong)(x).path) >> Shiftconv) & Maskconv )
49 #define PROTO(x) ( (((ulong)(x).path) >> Shiftproto) & Maskproto )
50 #define QID(p, c, y) ( ((p)<<(Shiftproto)) | ((c)<<Shiftconv) | (y) )
52 static char network[] = "network";
55 Fs *ipfs[Nfs]; /* attached fs's */
58 extern void nullmediumlink(void);
59 extern void pktmediumlink(void);
60 long ndbwrite(Fs *f, char *a, ulong off, int n);
63 ip3gen(Chan *c, int i, Dir *dp)
69 cv = ipfs[c->dev]->p[PROTO(c->qid)]->conv[CONV(c->qid)];
71 kstrdup(&cv->owner, eve);
72 mkqid(&q, QID(PROTO(c->qid), CONV(c->qid), i), 0, QTFILE);
78 devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp);
81 devdir(c, q, "data", qlen(cv->rq), cv->owner, cv->perm, dp);
84 devdir(c, q, "err", qlen(cv->eq), cv->owner, cv->perm, dp);
87 devdir(c, q, "listen", 0, cv->owner, cv->perm, dp);
96 if(strcmp(cv->p->name, "ipifc") != 0)
98 devdir(c, q, "snoop", qlen(cv->sq), cv->owner, 0400, dp);
104 devdir(c, q, p, 0, cv->owner, 0444, dp);
109 ip2gen(Chan *c, int i, Dir *dp)
115 mkqid(&q, QID(PROTO(c->qid), 0, Qclone), 0, QTFILE);
116 devdir(c, q, "clone", 0, network, 0666, dp);
119 mkqid(&q, QID(PROTO(c->qid), 0, Qstats), 0, QTFILE);
120 devdir(c, q, "stats", 0, network, 0444, dp);
127 ip1gen(Chan *c, int i, Dir *dp)
134 extern ulong kerndate;
139 mkqid(&q, QID(0, 0, i), 0, QTFILE);
152 len = strlen(f->ndb);
167 devdir(c, q, p, len, network, prot, dp);
168 if(i == Qndb && f->ndbmtime > kerndate)
169 dp->mtime = f->ndbmtime;
174 ipgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
182 switch(TYPE(c->qid)) {
185 mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR);
186 snprint(up->genbuf, sizeof up->genbuf, "#I%lud", c->dev);
187 devdir(c, q, up->genbuf, 0, network, 0555, dp);
191 if(f->p[s]->connect == nil)
192 return 0; /* protocol with no user interface */
193 mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR);
194 devdir(c, q, f->p[s]->name, 0, network, 0555, dp);
198 return ip1gen(c, s+Qtopbase, dp);
205 return ip1gen(c, TYPE(c->qid), dp);
208 mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR);
209 snprint(up->genbuf, sizeof up->genbuf, "#I%lud", c->dev);
210 devdir(c, q, up->genbuf, 0, network, 0555, dp);
213 if(s < f->p[PROTO(c->qid)]->ac) {
214 cv = f->p[PROTO(c->qid)]->conv[s];
215 snprint(up->genbuf, sizeof up->genbuf, "%d", s);
216 mkqid(&q, QID(PROTO(c->qid), s, Qconvdir), 0, QTDIR);
217 devdir(c, q, up->genbuf, 0, cv->owner, 0555, dp);
220 s -= f->p[PROTO(c->qid)]->ac;
221 return ip2gen(c, s+Qprotobase, dp);
224 return ip2gen(c, TYPE(c->qid), dp);
228 mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR);
229 devdir(c, q, f->p[s]->name, 0, network, 0555, dp);
232 return ip3gen(c, s+Qconvbase, dp);
241 return ip3gen(c, TYPE(c->qid), dp);
252 fmtinstall('i', eipfmt);
253 fmtinstall('I', eipfmt);
254 fmtinstall('E', eipfmt);
255 fmtinstall('V', eipfmt);
256 fmtinstall('M', eipfmt);
260 newipaux(char *owner, char *tag)
265 a = smalloc(sizeof(*a));
266 kstrdup(&a->owner, owner);
267 memset(a->tag, ' ', sizeof(a->tag));
269 if(n > sizeof(a->tag))
271 memmove(a->tag, tag, n);
275 #define ATTACHER(c) (((IPaux*)((c)->aux))->owner)
283 dev = strtoul(spec, nil, 10);
288 if(ipfs[dev] == nil){
289 extern void (*ipprotoinit[])(Fs*);
293 f = smalloc(sizeof(Fs));
297 for(i = 0; ipprotoinit[i]; i++)
304 c = devattach('I', spec);
305 mkqid(&c->qid, QID(0, 0, Qtopdir), 0, QTDIR);
308 c->aux = newipaux(commonuser(), "none");
314 ipwalk(Chan* c, Chan *nc, char **name, int nname)
319 w = devwalk(c, nc, name, nname, nil, 0, ipgen);
320 if(w != nil && w->clone != nil)
321 w->clone->aux = newipaux(a->owner, a->tag);
327 ipstat(Chan* c, uchar* db, int n)
329 return devstat(c, db, n, nil, 0, ipgen);
338 return conv->incall != nil;
348 ipopen(Chan* c, int omode)
359 switch(TYPE(c->qid)) {
363 if(omode & (OWRITE|OTRUNC) && !iseve())
365 if((omode & (OWRITE|OTRUNC)) == (OWRITE|OTRUNC))
373 if(omode != OREAD && !iseve())
391 p = f->p[PROTO(c->qid)];
392 cv = p->conv[CONV(c->qid)];
393 if(strcmp(ATTACHER(c), cv->owner) != 0 && !iseve())
395 incref(&cv->snoopers);
398 p = f->p[PROTO(c->qid)];
400 cv = Fsprotoclone(p, ATTACHER(c));
406 mkqid(&c->qid, QID(p->x, cv->x, Qctl), 0, QTFILE);
411 p = f->p[PROTO(c->qid)];
413 cv = p->conv[CONV(c->qid)];
420 if((perm & (cv->perm>>6)) != perm) {
421 if(strcmp(ATTACHER(c), cv->owner) != 0)
423 if((perm & cv->perm) != perm)
429 kstrdup(&cv->owner, ATTACHER(c));
437 cv = f->p[PROTO(c->qid)]->conv[CONV(c->qid)];
438 if((perm & (cv->perm>>6)) != perm) {
439 if(strcmp(ATTACHER(c), cv->owner) != 0)
441 if((perm & cv->perm) != perm)
446 if(cv->state != Announced)
447 error("not announced");
459 /* give up if we got a hangup */
460 if(qisclosed(cv->rq))
461 error("listen hungup");
465 qunlock(&cv->listenq);
469 /* wait for a connect */
470 sleep(&cv->listenr, incoming, cv);
475 cv->incall = nc->next;
476 mkqid(&c->qid, QID(PROTO(c->qid), nc->x, Qctl), 0, QTFILE);
477 kstrdup(&cv->owner, ATTACHER(c));
481 qunlock(&cv->listenq);
488 c->mode = openmode(omode);
495 ipcreate(Chan*, char*, int, ulong)
508 ipwstat(Chan *c, uchar *dp, int n)
516 switch(TYPE(c->qid)) {
525 n = convM2D(dp, n, &d, nil);
527 p = f->p[PROTO(c->qid)];
528 cv = p->conv[CONV(c->qid)];
529 if(!iseve() && strcmp(ATTACHER(c), cv->owner) != 0)
532 kstrdup(&cv->owner, d.uid);
533 cv->perm = d.mode & 0777;
546 if(--cv->inuse > 0) {
551 /* close all incoming calls since no listen will ever happen */
552 for(nc = cv->incall; nc != nil; nc = cv->incall){
553 cv->incall = nc->next;
558 kstrdup(&cv->owner, network);
561 while((mp = cv->multi) != nil)
562 ipifcremmulti(cv, mp->ma, mp->ia);
564 if(cv->p->close != nil)
577 switch(TYPE(c->qid)) {
588 closeconv(f->p[PROTO(c->qid)]->conv[CONV(c->qid)]);
592 decref(&f->p[PROTO(c->qid)]->conv[CONV(c->qid)]->snoopers);
595 free(((IPaux*)c->aux)->owner);
605 ipread(Chan *ch, void *a, long n, vlong off)
617 switch(TYPE(ch->qid)) {
623 return devdirread(ch, a, n, 0, 0, ipgen);
625 return arpread(f->arp, a, offset, n);
627 return bootpread(a, offset, n);
629 return readstr(offset, a, n, f->ndb);
631 return routeread(f, a, offset, n);
633 return ipselftabread(f, a, offset, n);
635 return netlogread(f, a, offset, n);
638 snprint(buf, 16, "%lud", CONV(ch->qid));
639 rv = readstr(offset, p, n, buf);
643 buf = smalloc(Statelen);
644 x = f->p[PROTO(ch->qid)];
645 c = x->conv[CONV(ch->qid)];
646 if(x->remote == nil) {
647 snprint(buf, Statelen, "%I!%d\n", c->raddr, c->rport);
649 (*x->remote)(c, buf, Statelen-2);
651 rv = readstr(offset, p, n, buf);
655 buf = smalloc(Statelen);
656 x = f->p[PROTO(ch->qid)];
657 c = x->conv[CONV(ch->qid)];
658 if(x->local == nil) {
659 snprint(buf, Statelen, "%I!%d\n", c->laddr, c->lport);
661 (*x->local)(c, buf, Statelen-2);
663 rv = readstr(offset, p, n, buf);
667 buf = smalloc(Statelen);
668 x = f->p[PROTO(ch->qid)];
669 c = x->conv[CONV(ch->qid)];
670 (*x->state)(c, buf, Statelen-2);
671 rv = readstr(offset, p, n, buf);
675 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
676 return qread(c->rq, a, n);
678 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
679 return qread(c->eq, a, n);
681 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
682 return qread(c->sq, a, n);
684 x = f->p[PROTO(ch->qid)];
686 error("stats not implemented");
687 buf = smalloc(Statelen);
688 (*x->stats)(x, buf, Statelen);
689 rv = readstr(offset, p, n, buf);
696 ipbread(Chan* ch, long n, ulong offset)
702 switch(TYPE(ch->qid)){
705 x = f->p[PROTO(ch->qid)];
706 c = x->conv[CONV(ch->qid)];
707 return qbread(c->rq, n);
709 return devbread(ch, n, offset);
714 * set local address to be that of the ifc closest to remote address
719 findlocalip(c->p->f, c->laddr, c->raddr);
723 * set a local port making sure the quad of raddr,rport,laddr,lport is unique
726 setluniqueport(Conv* c, int lport)
735 for(x = 0; x < p->nc; x++){
741 if((xp->state == Connected || xp->state == Announced)
742 && xp->lport == lport
743 && xp->rport == c->rport
744 && ipcmp(xp->raddr, c->raddr) == 0
745 && ipcmp(xp->laddr, c->laddr) == 0){
747 return "address in use";
756 * is lport in use by anyone?
759 lportinuse(Proto *p, ushort lport)
763 for(x = 0; x < p->nc && p->conv[x]; x++)
764 if(p->conv[x]->lport == lport)
770 * pick a local port and set it
781 /* Restricted ports cycle between 600 and 1024. */
782 for(i=0; i<1024-600; i++){
783 if(p->nextrport >= 1024 || p->nextrport < 600)
785 port = p->nextrport++;
786 if(!lportinuse(p, port))
791 * Unrestricted ports are chosen randomly
792 * between 2^15 and 2^16. There are at most
793 * 4*Nchan = 4096 ports in use at any given time,
794 * so even in the worst case, a random probe has a
795 * 1 - 4096/2^15 = 87% chance of success.
796 * If 64 successive probes fail, there is a bug somewhere
797 * (or a once in 10^58 event has happened, but that's
798 * less likely than a venti collision).
801 port = (1<<15) + nrand(1<<15);
802 if(!lportinuse(p, port))
807 return "no ports available";
816 * set a local address and port from a string of the form
820 setladdrport(Conv* c, char* str, int announcing)
825 uchar addr[IPaddrlen];
828 * ignore restricted part if it exists. it's
829 * meaningless on local ports.
831 p = strchr(str, '!');
834 if(strcmp(p, "r") == 0)
841 ipmove(c->laddr, IPnoaddr);
846 if(strcmp(str, "*") == 0)
847 ipmove(c->laddr, IPnoaddr);
849 if(parseip(addr, str) == -1)
851 if(ipforme(c->p->f, addr) != 0 || ipismulticast(addr))
852 ipmove(c->laddr, addr);
854 return "not a local IP address";
858 /* one process can get all connections */
859 if(announcing && strcmp(p, "*") == 0){
862 return setluniqueport(c, 0);
869 rv = setluniqueport(c, lport);
874 setraddrport(Conv* c, char* str)
878 p = strchr(str, '!');
880 return "malformed address";
882 if (parseip(c->raddr, str) == -1)
887 if(strstr(p, "!r") != nil)
894 * called by protocol connect routine to set addresses
897 Fsstdconnect(Conv *c, char *argv[], int argc)
903 return "bad args to connect";
905 p = setraddrport(c, argv[1]);
914 p = setraddrport(c, argv[1]);
917 p = setladdrport(c, argv[2], 0);
922 c->ipversion = convipvers(c);
927 * initiate connection and sleep till its set up
932 return ((Conv*)a)->state == Connected;
935 connectctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
941 c->state = Connecting;
943 if(x->connect == nil)
944 error("connect not supported");
945 p = x->connect(c, cb->f, cb->nf);
954 sleep(&c->cr, connected, c);
958 if(c->cerr[0] != '\0')
963 * called by protocol announce routine to set addresses
966 Fsstdannounce(Conv* c, char* argv[], int argc)
968 memset(c->raddr, 0, sizeof(c->raddr));
974 return setladdrport(c, argv[1], 1);
976 return "bad args to announce";
980 * initiate announcement and sleep till its set up
985 return ((Conv*)a)->state == Announced;
988 announcectlmsg(Proto *x, Conv *c, Cmdbuf *cb)
994 c->state = Announcing;
996 if(x->announce == nil)
997 error("announce not supported");
998 p = x->announce(c, cb->f, cb->nf);
1007 sleep(&c->cr, announced, c);
1011 if(c->cerr[0] != '\0')
1016 * called by protocol bind routine to set addresses
1019 Fsstdbind(Conv* c, char* argv[], int argc)
1025 return setladdrport(c, argv[1], 0);
1027 return "bad args to bind";
1031 bindctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
1036 p = Fsstdbind(c, cb->f, cb->nf);
1038 p = x->bind(c, cb->f, cb->nf);
1044 tosctlmsg(Conv *c, Cmdbuf *cb)
1049 c->tos = atoi(cb->f[1]);
1053 ttlctlmsg(Conv *c, Cmdbuf *cb)
1058 c->ttl = atoi(cb->f[1]);
1062 ipwrite(Chan* ch, void *v, long n, vlong off)
1068 uchar ia[IPaddrlen], ma[IPaddrlen];
1076 switch(TYPE(ch->qid)){
1080 x = f->p[PROTO(ch->qid)];
1081 c = x->conv[CONV(ch->qid)];
1086 qwrite(c->wq, a, n);
1089 return arpwrite(f, a, n);
1091 return routewrite(f, ch, a, n);
1096 return ndbwrite(f, a, offset, n);
1099 x = f->p[PROTO(ch->qid)];
1100 c = x->conv[CONV(ch->qid)];
1101 cb = parsecmd(a, n);
1110 error("short control request");
1111 if(strcmp(cb->f[0], "connect") == 0)
1112 connectctlmsg(x, c, cb);
1113 else if(strcmp(cb->f[0], "announce") == 0)
1114 announcectlmsg(x, c, cb);
1115 else if(strcmp(cb->f[0], "bind") == 0)
1116 bindctlmsg(x, c, cb);
1117 else if(strcmp(cb->f[0], "ttl") == 0)
1119 else if(strcmp(cb->f[0], "tos") == 0)
1121 else if(strcmp(cb->f[0], "ignoreadvice") == 0)
1122 c->ignoreadvice = 1;
1123 else if(strcmp(cb->f[0], "addmulti") == 0){
1125 error("addmulti needs interface address");
1127 if(!ipismulticast(c->raddr))
1128 error("addmulti for a non multicast address");
1129 if (parseip(ia, cb->f[1]) == -1)
1131 ipifcaddmulti(c, c->raddr, ia);
1133 if (parseip(ia, cb->f[1]) == -1 ||
1134 parseip(ma, cb->f[2]) == -1)
1136 if(!ipismulticast(ma))
1137 error("addmulti for a non multicast address");
1138 ipifcaddmulti(c, ma, ia);
1140 } else if(strcmp(cb->f[0], "remmulti") == 0){
1142 error("remmulti needs interface address");
1143 if(!ipismulticast(c->raddr))
1144 error("remmulti for a non multicast address");
1145 if (parseip(ia, cb->f[1]) == -1)
1147 ipifcremmulti(c, c->raddr, ia);
1148 } else if(x->ctl != nil) {
1149 p = x->ctl(c, cb->f, cb->nf);
1153 error("unknown control request");
1162 ipbwrite(Chan* ch, Block* bp, ulong offset)
1168 switch(TYPE(ch->qid)){
1171 x = f->p[PROTO(ch->qid)];
1172 c = x->conv[CONV(ch->qid)];
1177 return qbwrite(c->wq, bp);
1179 return devbwrite(ch, bp, offset);
1205 Fsproto(Fs *f, Proto *p)
1207 if(f->np >= Maxproto)
1213 if(f->t2p[p->ipproto] != nil)
1215 f->t2p[p->ipproto] = p;
1218 p->qid.type = QTDIR;
1219 p->qid.path = QID(f->np, 0, Qprotodir);
1220 if(p->nc > Maskconv+1){
1221 print("Fsproto: %s nc %d > %d\n", p->name, p->nc, Maskconv+1);
1224 p->conv = malloc(sizeof(Conv*)*(p->nc+1));
1236 * return true if this protocol is
1240 Fsbuiltinproto(Fs* f, uchar proto)
1242 return f->t2p[proto] != nil;
1246 * called with protocol locked
1249 Fsprotoclone(Proto *p, char *user)
1251 Conv *c, **pp, **ep;
1255 ep = &p->conv[p->nc];
1256 for(pp = p->conv; pp < ep; pp++) {
1259 c = malloc(sizeof(Conv));
1272 c->x = pp - p->conv;
1273 if(p->ptclsize != 0){
1274 c->ptcl = malloc(p->ptclsize);
1278 c->eq = qopen(1024, Qmsg, 0, 0);
1282 if(c->rq == nil || c->wq == nil)
1292 * make sure both processes and protocol
1293 * are done with this Conv
1295 if(c->inuse == 0 && (p->inuse == nil || (*p->inuse)(c) == 0))
1303 print("Fsprotoclone: garbage collecting %s Convs\n", p->name);
1311 kstrdup(&c->owner, user);
1314 ipmove(c->laddr, IPnoaddr);
1315 ipmove(c->raddr, IPnoaddr);
1321 c->ignoreadvice = 0;
1333 Fsconnected(Conv* c, char* msg)
1335 if(msg != nil && *msg != '\0')
1336 strncpy(c->cerr, msg, ERRMAX-1);
1341 c->state = Announced;
1345 c->state = Connected;
1354 Fsrcvpcol(Fs* f, uchar proto)
1359 return f->t2p[proto];
1363 Fsrcvpcolx(Fs *f, uchar proto)
1365 return f->t2p[proto];
1369 * called with protocol locked
1372 Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport, uchar version)
1380 for(l = &c->incall; *l; l = &(*l)->next)
1382 if(i >= Maxincall) {
1383 static int beenhere;
1388 print("Fsnewcall: incall queue full (%d) on port %d\n",
1394 /* find a free conversation */
1395 nc = Fsprotoclone(c->p, network);
1400 ipmove(nc->raddr, raddr);
1402 ipmove(nc->laddr, laddr);
1406 nc->state = Connected;
1407 nc->ipversion = version;
1411 wakeup(&c->listenr);
1417 ndbwrite(Fs *f, char *a, ulong off, int n)
1419 if(off > strlen(f->ndb))
1421 if(off+n >= sizeof(f->ndb))
1423 memmove(f->ndb+off, a, n);
1426 f->ndbmtime = seconds();
1433 if(cpuserver && conf.npage*BY2PG >= 128*MB)