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)];
414 cv = Fsprotoclone(p, ATTACHER(c));
421 mkqid(&c->qid, QID(p->x, cv->x, Qctl), 0, QTFILE);
426 p = f->p[PROTO(c->qid)];
428 cv = p->conv[CONV(c->qid)];
435 if((perm & (cv->perm>>6)) != perm) {
436 if(strcmp(ATTACHER(c), cv->owner) != 0)
438 if((perm & cv->perm) != perm)
444 kstrdup(&cv->owner, ATTACHER(c));
452 cv = f->p[PROTO(c->qid)]->conv[CONV(c->qid)];
453 if((perm & (cv->perm>>6)) != perm) {
454 if(strcmp(ATTACHER(c), cv->owner) != 0)
456 if((perm & cv->perm) != perm)
461 if(cv->state != Announced)
462 error("not announced");
474 /* give up if we got a hangup */
475 if(qisclosed(cv->rq))
476 error("listen hungup");
480 qunlock(&cv->listenq);
484 /* wait for a connect */
485 sleep(&cv->listenr, incoming, cv);
490 cv->incall = nc->next;
491 mkqid(&c->qid, QID(PROTO(c->qid), nc->x, Qctl), 0, QTFILE);
492 kstrdup(&cv->owner, ATTACHER(c));
496 qunlock(&cv->listenq);
503 c->mode = openmode(omode);
510 ipcreate(Chan*, char*, int, ulong)
523 ipwstat(Chan *c, uchar *dp, int n)
531 switch(TYPE(c->qid)) {
540 n = convM2D(dp, n, &d, nil);
542 p = f->p[PROTO(c->qid)];
543 cv = p->conv[CONV(c->qid)];
544 if(!iseve() && strcmp(ATTACHER(c), cv->owner) != 0)
547 kstrdup(&cv->owner, d.uid);
548 cv->perm = d.mode & 0777;
561 if(--cv->inuse > 0) {
566 /* close all incoming calls since no listen will ever happen */
567 for(nc = cv->incall; nc; nc = cv->incall){
568 cv->incall = nc->next;
573 kstrdup(&cv->owner, network);
576 while((mp = cv->multi) != nil)
577 ipifcremmulti(cv, mp->ma, mp->ia);
592 switch(TYPE(c->qid)) {
603 closeconv(f->p[PROTO(c->qid)]->conv[CONV(c->qid)]);
607 decref(&f->p[PROTO(c->qid)]->conv[CONV(c->qid)]->snoopers);
610 free(((IPaux*)c->aux)->owner);
620 ipread(Chan *ch, void *a, long n, vlong off)
632 switch(TYPE(ch->qid)) {
638 return devdirread(ch, a, n, 0, 0, ipgen);
640 return arpread(f->arp, a, offset, n);
642 return bootpread(a, offset, n);
644 return readstr(offset, a, n, f->ndb);
646 return routeread(f, a, offset, n);
648 return ipselftabread(f, a, offset, n);
650 return netlogread(f, a, offset, n);
653 snprint(buf, 16, "%lud", CONV(ch->qid));
654 rv = readstr(offset, p, n, buf);
658 buf = smalloc(Statelen);
659 x = f->p[PROTO(ch->qid)];
660 c = x->conv[CONV(ch->qid)];
661 if(x->remote == nil) {
662 snprint(buf, Statelen, "%I!%d\n", c->raddr, c->rport);
664 (*x->remote)(c, buf, Statelen-2);
666 rv = readstr(offset, p, n, buf);
670 buf = smalloc(Statelen);
671 x = f->p[PROTO(ch->qid)];
672 c = x->conv[CONV(ch->qid)];
673 if(x->local == nil) {
674 snprint(buf, Statelen, "%I!%d\n", c->laddr, c->lport);
676 (*x->local)(c, buf, Statelen-2);
678 rv = readstr(offset, p, n, buf);
682 buf = smalloc(Statelen);
683 x = f->p[PROTO(ch->qid)];
684 c = x->conv[CONV(ch->qid)];
685 (*x->state)(c, buf, Statelen-2);
686 rv = readstr(offset, p, n, buf);
690 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
691 return qread(c->rq, a, n);
693 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
694 return qread(c->eq, a, n);
696 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
697 return qread(c->sq, a, n);
699 x = f->p[PROTO(ch->qid)];
701 error("stats not implemented");
702 buf = smalloc(Statelen);
703 (*x->stats)(x, buf, Statelen);
704 rv = readstr(offset, p, n, buf);
711 ipbread(Chan* ch, long n, ulong offset)
717 switch(TYPE(ch->qid)){
720 x = f->p[PROTO(ch->qid)];
721 c = x->conv[CONV(ch->qid)];
722 return qbread(c->rq, n);
724 return devbread(ch, n, offset);
729 * set local address to be that of the ifc closest to remote address
734 findlocalip(c->p->f, c->laddr, c->raddr);
738 * set a local port making sure the quad of raddr,rport,laddr,lport is unique
741 setluniqueport(Conv* c, int lport)
750 for(x = 0; x < p->nc; x++){
756 if((xp->state == Connected || xp->state == Announced)
757 && xp->lport == lport
758 && xp->rport == c->rport
759 && ipcmp(xp->raddr, c->raddr) == 0
760 && ipcmp(xp->laddr, c->laddr) == 0){
762 return "address in use";
771 * is lport in use by anyone?
774 lportinuse(Proto *p, ushort lport)
778 for(x = 0; x < p->nc && p->conv[x]; x++)
779 if(p->conv[x]->lport == lport)
785 * pick a local port and set it
796 /* Restricted ports cycle between 600 and 1024. */
797 for(i=0; i<1024-600; i++){
798 if(p->nextrport >= 1024 || p->nextrport < 600)
800 port = p->nextrport++;
801 if(!lportinuse(p, port))
806 * Unrestricted ports are chosen randomly
807 * between 2^15 and 2^16. There are at most
808 * 4*Nchan = 4096 ports in use at any given time,
809 * so even in the worst case, a random probe has a
810 * 1 - 4096/2^15 = 87% chance of success.
811 * If 64 successive probes fail, there is a bug somewhere
812 * (or a once in 10^58 event has happened, but that's
813 * less likely than a venti collision).
816 port = (1<<15) + nrand(1<<15);
817 if(!lportinuse(p, port))
822 return "no ports available";
831 * set a local address and port from a string of the form
835 setladdrport(Conv* c, char* str, int announcing)
840 uchar addr[IPaddrlen];
843 * ignore restricted part if it exists. it's
844 * meaningless on local ports.
846 p = strchr(str, '!');
849 if(strcmp(p, "r") == 0)
856 ipmove(c->laddr, IPnoaddr);
861 if(strcmp(str, "*") == 0)
862 ipmove(c->laddr, IPnoaddr);
864 if(parseip(addr, str) == -1)
866 if(ipforme(c->p->f, addr))
867 ipmove(c->laddr, addr);
869 return "not a local IP address";
873 /* one process can get all connections */
874 if(announcing && strcmp(p, "*") == 0){
877 return setluniqueport(c, 0);
884 rv = setluniqueport(c, lport);
889 setraddrport(Conv* c, char* str)
893 p = strchr(str, '!');
895 return "malformed address";
897 if (parseip(c->raddr, str) == -1)
902 if(strstr(p, "!r") != nil)
909 * called by protocol connect routine to set addresses
912 Fsstdconnect(Conv *c, char *argv[], int argc)
918 return "bad args to connect";
920 p = setraddrport(c, argv[1]);
929 p = setraddrport(c, argv[1]);
932 p = setladdrport(c, argv[2], 0);
937 if( (memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
938 memcmp(c->laddr, v4prefix, IPv4off) == 0)
939 || ipcmp(c->raddr, IPnoaddr) == 0)
947 * initiate connection and sleep till its set up
952 return ((Conv*)a)->state == Connected;
955 connectctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
961 c->state = Connecting;
963 if(x->connect == nil)
964 error("connect not supported");
965 p = x->connect(c, cb->f, cb->nf);
974 sleep(&c->cr, connected, c);
978 if(c->cerr[0] != '\0')
983 * called by protocol announce routine to set addresses
986 Fsstdannounce(Conv* c, char* argv[], int argc)
988 memset(c->raddr, 0, sizeof(c->raddr));
994 return setladdrport(c, argv[1], 1);
996 return "bad args to announce";
1000 * initiate announcement and sleep till its set up
1005 return ((Conv*)a)->state == Announced;
1008 announcectlmsg(Proto *x, Conv *c, Cmdbuf *cb)
1014 c->state = Announcing;
1016 if(x->announce == nil)
1017 error("announce not supported");
1018 p = x->announce(c, cb->f, cb->nf);
1027 sleep(&c->cr, announced, c);
1031 if(c->cerr[0] != '\0')
1036 * called by protocol bind routine to set addresses
1039 Fsstdbind(Conv* c, char* argv[], int argc)
1045 return setladdrport(c, argv[1], 0);
1047 return "bad args to bind";
1051 bindctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
1056 p = Fsstdbind(c, cb->f, cb->nf);
1058 p = x->bind(c, cb->f, cb->nf);
1064 tosctlmsg(Conv *c, Cmdbuf *cb)
1069 c->tos = atoi(cb->f[1]);
1073 ttlctlmsg(Conv *c, Cmdbuf *cb)
1078 c->ttl = atoi(cb->f[1]);
1082 ipwrite(Chan* ch, void *v, long n, vlong off)
1088 uchar ia[IPaddrlen], ma[IPaddrlen];
1096 switch(TYPE(ch->qid)){
1100 x = f->p[PROTO(ch->qid)];
1101 c = x->conv[CONV(ch->qid)];
1106 qwrite(c->wq, a, n);
1109 return arpwrite(f, a, n);
1111 return routewrite(f, ch, a, n);
1116 return ndbwrite(f, a, offset, n);
1119 x = f->p[PROTO(ch->qid)];
1120 c = x->conv[CONV(ch->qid)];
1121 cb = parsecmd(a, n);
1130 error("short control request");
1131 if(strcmp(cb->f[0], "connect") == 0)
1132 connectctlmsg(x, c, cb);
1133 else if(strcmp(cb->f[0], "announce") == 0)
1134 announcectlmsg(x, c, cb);
1135 else if(strcmp(cb->f[0], "bind") == 0)
1136 bindctlmsg(x, c, cb);
1137 else if(strcmp(cb->f[0], "ttl") == 0)
1139 else if(strcmp(cb->f[0], "tos") == 0)
1141 else if(strcmp(cb->f[0], "ignoreadvice") == 0)
1142 c->ignoreadvice = 1;
1143 else if(strcmp(cb->f[0], "addmulti") == 0){
1145 error("addmulti needs interface address");
1147 if(!ipismulticast(c->raddr))
1148 error("addmulti for a non multicast address");
1149 if (parseip(ia, cb->f[1]) == -1)
1151 ipifcaddmulti(c, c->raddr, ia);
1153 if (parseip(ia, cb->f[1]) == -1 ||
1154 parseip(ma, cb->f[2]) == -1)
1156 if(!ipismulticast(ma))
1157 error("addmulti for a non multicast address");
1158 ipifcaddmulti(c, ma, ia);
1160 } else if(strcmp(cb->f[0], "remmulti") == 0){
1162 error("remmulti needs interface address");
1163 if(!ipismulticast(c->raddr))
1164 error("remmulti for a non multicast address");
1165 if (parseip(ia, cb->f[1]) == -1)
1167 ipifcremmulti(c, c->raddr, ia);
1168 } else if(strcmp(cb->f[0], "maxfragsize") == 0){
1170 error("maxfragsize needs size");
1172 c->maxfragsize = (int)strtol(cb->f[1], nil, 0);
1174 } else if(x->ctl != nil) {
1175 p = x->ctl(c, cb->f, cb->nf);
1179 error("unknown control request");
1188 ipbwrite(Chan* ch, Block* bp, ulong offset)
1195 switch(TYPE(ch->qid)){
1198 x = f->p[PROTO(ch->qid)];
1199 c = x->conv[CONV(ch->qid)];
1205 bp = concatblock(bp);
1210 return devbwrite(ch, bp, offset);
1236 Fsproto(Fs *f, Proto *p)
1238 if(f->np >= Maxproto)
1244 if(f->t2p[p->ipproto] != nil)
1246 f->t2p[p->ipproto] = p;
1249 p->qid.type = QTDIR;
1250 p->qid.path = QID(f->np, 0, Qprotodir);
1251 p->conv = malloc(sizeof(Conv*)*(p->nc+1));
1263 * return true if this protocol is
1267 Fsbuiltinproto(Fs* f, uchar proto)
1269 return f->t2p[proto] != nil;
1273 * called with protocol locked
1276 Fsprotoclone(Proto *p, char *user)
1278 Conv *c, **pp, **ep;
1282 ep = &p->conv[p->nc];
1283 for(pp = p->conv; pp < ep; pp++) {
1286 c = malloc(sizeof(Conv));
1291 c->x = pp - p->conv;
1292 if(p->ptclsize != 0){
1293 c->ptcl = malloc(p->ptclsize);
1294 if(c->ptcl == nil) {
1301 c->eq = qopen(1024, Qmsg, 0, 0);
1307 * make sure both processes and protocol
1308 * are done with this Conv
1310 if(c->inuse == 0 && (p->inuse == nil || (*p->inuse)(c) == 0))
1318 print("Fsprotoclone: garbage collecting Convs\n");
1319 if(p->gc != nil && (*p->gc)(p))
1325 kstrdup(&c->owner, user);
1328 ipmove(c->laddr, IPnoaddr);
1329 ipmove(c->raddr, IPnoaddr);
1346 Fsconnected(Conv* c, char* msg)
1348 if(msg != nil && *msg != '\0')
1349 strncpy(c->cerr, msg, ERRMAX-1);
1354 c->state = Announced;
1358 c->state = Connected;
1367 Fsrcvpcol(Fs* f, uchar proto)
1372 return f->t2p[proto];
1376 Fsrcvpcolx(Fs *f, uchar proto)
1378 return f->t2p[proto];
1382 * called with protocol locked
1385 Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport, uchar version)
1393 for(l = &c->incall; *l; l = &(*l)->next)
1395 if(i >= Maxincall) {
1396 static int beenhere;
1401 print("Fsnewcall: incall queue full (%d) on port %d\n",
1407 /* find a free conversation */
1408 nc = Fsprotoclone(c->p, network);
1413 ipmove(nc->raddr, raddr);
1415 ipmove(nc->laddr, laddr);
1419 nc->state = Connected;
1420 nc->ipversion = version;
1424 wakeup(&c->listenr);
1430 ndbwrite(Fs *f, char *a, ulong off, int n)
1432 if(off > strlen(f->ndb))
1434 if(off+n >= sizeof(f->ndb))
1436 memmove(f->ndb+off, a, n);
1439 f->ndbmtime = seconds();
1446 if(cpuserver && conf.npage*BY2PG >= 128*MB)