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);
262 extern void (*ipprotoinit[])(Fs*);
270 if(ipfs[dev] == nil){
271 f = smalloc(sizeof(Fs));
275 for(i = 0; ipprotoinit[i]; i++)
286 newipaux(char *owner, char *tag)
291 a = smalloc(sizeof(*a));
292 kstrdup(&a->owner, owner);
293 memset(a->tag, ' ', sizeof(a->tag));
295 if(n > sizeof(a->tag))
297 memmove(a->tag, tag, n);
301 #define ATTACHER(c) (((IPaux*)((c)->aux))->owner)
311 error("bad specification");
314 c = devattach('I', spec);
315 mkqid(&c->qid, QID(0, 0, Qtopdir), 0, QTDIR);
318 c->aux = newipaux(commonuser(), "none");
324 ipwalk(Chan* c, Chan *nc, char **name, int nname)
329 w = devwalk(c, nc, name, nname, nil, 0, ipgen);
330 if(w != nil && w->clone != nil)
331 w->clone->aux = newipaux(a->owner, a->tag);
337 ipstat(Chan* c, uchar* db, int n)
339 return devstat(c, db, n, nil, 0, ipgen);
348 return conv->incall != nil;
358 ipopen(Chan* c, int omode)
369 switch(TYPE(c->qid)) {
373 if(omode & (OWRITE|OTRUNC) && !iseve())
375 if((omode & (OWRITE|OTRUNC)) == (OWRITE|OTRUNC))
383 if(omode != OREAD && !iseve())
401 p = f->p[PROTO(c->qid)];
402 cv = p->conv[CONV(c->qid)];
403 if(strcmp(ATTACHER(c), cv->owner) != 0 && !iseve())
405 incref(&cv->snoopers);
408 p = f->p[PROTO(c->qid)];
410 cv = Fsprotoclone(p, ATTACHER(c));
416 mkqid(&c->qid, QID(p->x, cv->x, Qctl), 0, QTFILE);
421 p = f->p[PROTO(c->qid)];
423 cv = p->conv[CONV(c->qid)];
430 if((perm & (cv->perm>>6)) != perm) {
431 if(strcmp(ATTACHER(c), cv->owner) != 0)
433 if((perm & cv->perm) != perm)
439 kstrdup(&cv->owner, ATTACHER(c));
447 cv = f->p[PROTO(c->qid)]->conv[CONV(c->qid)];
448 if((perm & (cv->perm>>6)) != perm) {
449 if(strcmp(ATTACHER(c), cv->owner) != 0)
451 if((perm & cv->perm) != perm)
456 if(cv->state != Announced)
457 error("not announced");
469 /* give up if we got a hangup */
470 if(qisclosed(cv->rq))
471 error("listen hungup");
475 qunlock(&cv->listenq);
479 /* wait for a connect */
480 sleep(&cv->listenr, incoming, cv);
485 cv->incall = nc->next;
486 mkqid(&c->qid, QID(PROTO(c->qid), nc->x, Qctl), 0, QTFILE);
487 kstrdup(&cv->owner, ATTACHER(c));
491 qunlock(&cv->listenq);
498 c->mode = openmode(omode);
505 ipcreate(Chan*, char*, int, ulong)
518 ipwstat(Chan *c, uchar *dp, int n)
526 switch(TYPE(c->qid)) {
535 n = convM2D(dp, n, &d, nil);
537 p = f->p[PROTO(c->qid)];
538 cv = p->conv[CONV(c->qid)];
539 if(!iseve() && strcmp(ATTACHER(c), cv->owner) != 0)
542 kstrdup(&cv->owner, d.uid);
543 cv->perm = d.mode & 0777;
556 if(--cv->inuse > 0) {
561 /* close all incoming calls since no listen will ever happen */
562 for(nc = cv->incall; nc; nc = cv->incall){
563 cv->incall = nc->next;
568 kstrdup(&cv->owner, network);
571 while((mp = cv->multi) != nil)
572 ipifcremmulti(cv, mp->ma, mp->ia);
587 switch(TYPE(c->qid)) {
598 closeconv(f->p[PROTO(c->qid)]->conv[CONV(c->qid)]);
602 decref(&f->p[PROTO(c->qid)]->conv[CONV(c->qid)]->snoopers);
605 free(((IPaux*)c->aux)->owner);
615 ipread(Chan *ch, void *a, long n, vlong off)
627 switch(TYPE(ch->qid)) {
633 return devdirread(ch, a, n, 0, 0, ipgen);
635 return arpread(f->arp, a, offset, n);
637 return bootpread(a, offset, n);
639 return readstr(offset, a, n, f->ndb);
641 return routeread(f, a, offset, n);
643 return ipselftabread(f, a, offset, n);
645 return netlogread(f, a, offset, n);
648 snprint(buf, 16, "%lud", CONV(ch->qid));
649 rv = readstr(offset, p, n, buf);
653 buf = smalloc(Statelen);
654 x = f->p[PROTO(ch->qid)];
655 c = x->conv[CONV(ch->qid)];
656 if(x->remote == nil) {
657 snprint(buf, Statelen, "%I!%d\n", c->raddr, c->rport);
659 (*x->remote)(c, buf, Statelen-2);
661 rv = readstr(offset, p, n, buf);
665 buf = smalloc(Statelen);
666 x = f->p[PROTO(ch->qid)];
667 c = x->conv[CONV(ch->qid)];
668 if(x->local == nil) {
669 snprint(buf, Statelen, "%I!%d\n", c->laddr, c->lport);
671 (*x->local)(c, buf, Statelen-2);
673 rv = readstr(offset, p, n, buf);
677 buf = smalloc(Statelen);
678 x = f->p[PROTO(ch->qid)];
679 c = x->conv[CONV(ch->qid)];
680 (*x->state)(c, buf, Statelen-2);
681 rv = readstr(offset, p, n, buf);
685 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
686 return qread(c->rq, a, n);
688 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
689 return qread(c->eq, a, n);
691 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
692 return qread(c->sq, a, n);
694 x = f->p[PROTO(ch->qid)];
696 error("stats not implemented");
697 buf = smalloc(Statelen);
698 (*x->stats)(x, buf, Statelen);
699 rv = readstr(offset, p, n, buf);
706 ipbread(Chan* ch, long n, ulong offset)
712 switch(TYPE(ch->qid)){
715 x = f->p[PROTO(ch->qid)];
716 c = x->conv[CONV(ch->qid)];
717 return qbread(c->rq, n);
719 return devbread(ch, n, offset);
724 * set local address to be that of the ifc closest to remote address
729 findlocalip(c->p->f, c->laddr, c->raddr);
733 * set a local port making sure the quad of raddr,rport,laddr,lport is unique
736 setluniqueport(Conv* c, int lport)
745 for(x = 0; x < p->nc; x++){
751 if((xp->state == Connected || xp->state == Announced)
752 && xp->lport == lport
753 && xp->rport == c->rport
754 && ipcmp(xp->raddr, c->raddr) == 0
755 && ipcmp(xp->laddr, c->laddr) == 0){
757 return "address in use";
766 * is lport in use by anyone?
769 lportinuse(Proto *p, ushort lport)
773 for(x = 0; x < p->nc && p->conv[x]; x++)
774 if(p->conv[x]->lport == lport)
780 * pick a local port and set it
791 /* Restricted ports cycle between 600 and 1024. */
792 for(i=0; i<1024-600; i++){
793 if(p->nextrport >= 1024 || p->nextrport < 600)
795 port = p->nextrport++;
796 if(!lportinuse(p, port))
801 * Unrestricted ports are chosen randomly
802 * between 2^15 and 2^16. There are at most
803 * 4*Nchan = 4096 ports in use at any given time,
804 * so even in the worst case, a random probe has a
805 * 1 - 4096/2^15 = 87% chance of success.
806 * If 64 successive probes fail, there is a bug somewhere
807 * (or a once in 10^58 event has happened, but that's
808 * less likely than a venti collision).
811 port = (1<<15) + nrand(1<<15);
812 if(!lportinuse(p, port))
817 return "no ports available";
826 * set a local address and port from a string of the form
830 setladdrport(Conv* c, char* str, int announcing)
835 uchar addr[IPaddrlen];
838 * ignore restricted part if it exists. it's
839 * meaningless on local ports.
841 p = strchr(str, '!');
844 if(strcmp(p, "r") == 0)
851 ipmove(c->laddr, IPnoaddr);
856 if(strcmp(str, "*") == 0)
857 ipmove(c->laddr, IPnoaddr);
859 if(parseip(addr, str) == -1)
861 if(ipforme(c->p->f, addr))
862 ipmove(c->laddr, addr);
864 return "not a local IP address";
868 /* one process can get all connections */
869 if(announcing && strcmp(p, "*") == 0){
872 return setluniqueport(c, 0);
879 rv = setluniqueport(c, lport);
884 setraddrport(Conv* c, char* str)
888 p = strchr(str, '!');
890 return "malformed address";
892 if (parseip(c->raddr, str) == -1)
897 if(strstr(p, "!r") != nil)
904 * called by protocol connect routine to set addresses
907 Fsstdconnect(Conv *c, char *argv[], int argc)
913 return "bad args to connect";
915 p = setraddrport(c, argv[1]);
924 p = setraddrport(c, argv[1]);
927 p = setladdrport(c, argv[2], 0);
932 if( (memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
933 memcmp(c->laddr, v4prefix, IPv4off) == 0)
934 || ipcmp(c->raddr, IPnoaddr) == 0)
942 * initiate connection and sleep till its set up
947 return ((Conv*)a)->state == Connected;
950 connectctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
956 c->state = Connecting;
958 if(x->connect == nil)
959 error("connect not supported");
960 p = x->connect(c, cb->f, cb->nf);
969 sleep(&c->cr, connected, c);
973 if(c->cerr[0] != '\0')
978 * called by protocol announce routine to set addresses
981 Fsstdannounce(Conv* c, char* argv[], int argc)
983 memset(c->raddr, 0, sizeof(c->raddr));
989 return setladdrport(c, argv[1], 1);
991 return "bad args to announce";
995 * initiate announcement and sleep till its set up
1000 return ((Conv*)a)->state == Announced;
1003 announcectlmsg(Proto *x, Conv *c, Cmdbuf *cb)
1009 c->state = Announcing;
1011 if(x->announce == nil)
1012 error("announce not supported");
1013 p = x->announce(c, cb->f, cb->nf);
1022 sleep(&c->cr, announced, c);
1026 if(c->cerr[0] != '\0')
1031 * called by protocol bind routine to set addresses
1034 Fsstdbind(Conv* c, char* argv[], int argc)
1040 return setladdrport(c, argv[1], 0);
1042 return "bad args to bind";
1046 bindctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
1051 p = Fsstdbind(c, cb->f, cb->nf);
1053 p = x->bind(c, cb->f, cb->nf);
1059 tosctlmsg(Conv *c, Cmdbuf *cb)
1064 c->tos = atoi(cb->f[1]);
1068 ttlctlmsg(Conv *c, Cmdbuf *cb)
1073 c->ttl = atoi(cb->f[1]);
1077 ipwrite(Chan* ch, void *v, long n, vlong off)
1083 uchar ia[IPaddrlen], ma[IPaddrlen];
1091 switch(TYPE(ch->qid)){
1095 x = f->p[PROTO(ch->qid)];
1096 c = x->conv[CONV(ch->qid)];
1101 qwrite(c->wq, a, n);
1104 return arpwrite(f, a, n);
1106 return routewrite(f, ch, a, n);
1111 return ndbwrite(f, a, offset, n);
1114 x = f->p[PROTO(ch->qid)];
1115 c = x->conv[CONV(ch->qid)];
1116 cb = parsecmd(a, n);
1125 error("short control request");
1126 if(strcmp(cb->f[0], "connect") == 0)
1127 connectctlmsg(x, c, cb);
1128 else if(strcmp(cb->f[0], "announce") == 0)
1129 announcectlmsg(x, c, cb);
1130 else if(strcmp(cb->f[0], "bind") == 0)
1131 bindctlmsg(x, c, cb);
1132 else if(strcmp(cb->f[0], "ttl") == 0)
1134 else if(strcmp(cb->f[0], "tos") == 0)
1136 else if(strcmp(cb->f[0], "ignoreadvice") == 0)
1137 c->ignoreadvice = 1;
1138 else if(strcmp(cb->f[0], "addmulti") == 0){
1140 error("addmulti needs interface address");
1142 if(!ipismulticast(c->raddr))
1143 error("addmulti for a non multicast address");
1144 if (parseip(ia, cb->f[1]) == -1)
1146 ipifcaddmulti(c, c->raddr, ia);
1148 if (parseip(ia, cb->f[1]) == -1 ||
1149 parseip(ma, cb->f[2]) == -1)
1151 if(!ipismulticast(ma))
1152 error("addmulti for a non multicast address");
1153 ipifcaddmulti(c, ma, ia);
1155 } else if(strcmp(cb->f[0], "remmulti") == 0){
1157 error("remmulti needs interface address");
1158 if(!ipismulticast(c->raddr))
1159 error("remmulti for a non multicast address");
1160 if (parseip(ia, cb->f[1]) == -1)
1162 ipifcremmulti(c, c->raddr, ia);
1163 } else if(strcmp(cb->f[0], "maxfragsize") == 0){
1165 error("maxfragsize needs size");
1167 c->maxfragsize = (int)strtol(cb->f[1], nil, 0);
1169 } else if(x->ctl != nil) {
1170 p = x->ctl(c, cb->f, cb->nf);
1174 error("unknown control request");
1183 ipbwrite(Chan* ch, Block* bp, ulong offset)
1190 switch(TYPE(ch->qid)){
1193 x = f->p[PROTO(ch->qid)];
1194 c = x->conv[CONV(ch->qid)];
1200 bp = concatblock(bp);
1205 return devbwrite(ch, bp, offset);
1231 Fsproto(Fs *f, Proto *p)
1233 if(f->np >= Maxproto)
1239 if(f->t2p[p->ipproto] != nil)
1241 f->t2p[p->ipproto] = p;
1244 p->qid.type = QTDIR;
1245 p->qid.path = QID(f->np, 0, Qprotodir);
1246 p->conv = malloc(sizeof(Conv*)*(p->nc+1));
1258 * return true if this protocol is
1262 Fsbuiltinproto(Fs* f, uchar proto)
1264 return f->t2p[proto] != nil;
1268 * called with protocol locked
1271 Fsprotoclone(Proto *p, char *user)
1273 Conv *c, **pp, **ep;
1277 ep = &p->conv[p->nc];
1278 for(pp = p->conv; pp < ep; pp++) {
1281 c = malloc(sizeof(Conv));
1294 c->x = pp - p->conv;
1295 if(p->ptclsize != 0){
1296 c->ptcl = malloc(p->ptclsize);
1300 c->eq = qopen(1024, Qmsg, 0, 0);
1304 if(c->rq == nil || c->wq == nil)
1314 * make sure both processes and protocol
1315 * are done with this Conv
1317 if(c->inuse == 0 && (p->inuse == nil || (*p->inuse)(c) == 0))
1325 print("Fsprotoclone: garbage collecting Convs\n");
1326 if(p->gc != nil && (*p->gc)(p))
1332 kstrdup(&c->owner, user);
1335 ipmove(c->laddr, IPnoaddr);
1336 ipmove(c->raddr, IPnoaddr);
1353 Fsconnected(Conv* c, char* msg)
1355 if(msg != nil && *msg != '\0')
1356 strncpy(c->cerr, msg, ERRMAX-1);
1361 c->state = Announced;
1365 c->state = Connected;
1374 Fsrcvpcol(Fs* f, uchar proto)
1379 return f->t2p[proto];
1383 Fsrcvpcolx(Fs *f, uchar proto)
1385 return f->t2p[proto];
1389 * called with protocol locked
1392 Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport, uchar version)
1400 for(l = &c->incall; *l; l = &(*l)->next)
1402 if(i >= Maxincall) {
1403 static int beenhere;
1408 print("Fsnewcall: incall queue full (%d) on port %d\n",
1414 /* find a free conversation */
1415 nc = Fsprotoclone(c->p, network);
1420 ipmove(nc->raddr, raddr);
1422 ipmove(nc->laddr, laddr);
1426 nc->state = Connected;
1427 nc->ipversion = version;
1431 wakeup(&c->listenr);
1437 ndbwrite(Fs *f, char *a, ulong off, int n)
1439 if(off > strlen(f->ndb))
1441 if(off+n >= sizeof(f->ndb))
1443 memmove(f->ndb+off, a, n);
1446 f->ndbmtime = seconds();
1453 if(cpuserver && conf.npage*BY2PG >= 128*MB)