Adds chaninfo()
[akaros.git] / kern / src / net / devip.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 enum
17 {
18         Qtopdir=        1,              /* top level directory */
19         Qtopbase,
20         Qarp=           Qtopbase,
21         Qbootp,
22         Qndb,
23         Qiproute,
24         Qiprouter,
25         Qipselftab,
26         Qlog,
27
28         Qprotodir,                      /* directory for a protocol */
29         Qprotobase,
30         Qclone=         Qprotobase,
31         Qstats,
32
33         Qconvdir,                       /* directory for a conversation */
34         Qconvbase,
35         Qctl=           Qconvbase,
36         Qdata,
37         Qerr,
38         Qlisten,
39         Qlocal,
40         Qremote,
41         Qstatus,
42         Qsnoop,
43
44         Logtype=        5,
45         Masktype=       (1<<Logtype)-1,
46         Logconv=        12,
47         Maskconv=       (1<<Logconv)-1,
48         Shiftconv=      Logtype,
49         Logproto=       8,
50         Maskproto=      (1<<Logproto)-1,
51         Shiftproto=     Logtype + Logconv,
52
53         Nfs=            32,
54 };
55 #define TYPE(x)         ( ((uint32_t)(x).path) & Masktype )
56 #define CONV(x)         ( (((uint32_t)(x).path) >> Shiftconv) & Maskconv )
57 #define PROTO(x)        ( (((uint32_t)(x).path) >> Shiftproto) & Maskproto )
58 #define QID(p, c, y)    ( ((p)<<(Shiftproto)) | ((c)<<Shiftconv) | (y))
59 static char network[] = "network";
60
61 qlock_t fslock;
62 struct Fs       *ipfs[Nfs];     /* attached fs's */
63 struct queue    *qlog;
64
65 extern  void nullmediumlink(void);
66 extern  void pktmediumlink(void);
67 extern char *eve;
68 static  long ndbwrite(struct Fs*, char *unused_char_p_t, uint32_t, int);
69 static  void    closeconv(struct conv*);
70
71 static int
72 ip3gen(struct chan *c, int i, struct dir *dp)
73 {
74         struct qid q;
75         struct conv *cv;
76         char *p;
77
78         cv = ipfs[c->dev]->p[PROTO(c->qid)]->conv[CONV(c->qid)];
79         if(cv->owner == NULL)
80                 kstrdup(&cv->owner, eve);
81         mkqid(&q, QID(PROTO(c->qid), CONV(c->qid), i), 0, QTFILE);
82
83         switch(i) {
84         default:
85                 return -1;
86         case Qctl:
87                 devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp);
88                 return 1;
89         case Qdata:
90                 devdir(c, q, "data", qlen(cv->rq), cv->owner, cv->perm, dp);
91                 return 1;
92         case Qerr:
93                 devdir(c, q, "err", qlen(cv->eq), cv->owner, cv->perm, dp);
94                 return 1;
95         case Qlisten:
96                 devdir(c, q, "listen", 0, cv->owner, cv->perm, dp);
97                 return 1;
98         case Qlocal:
99                 p = "local";
100                 break;
101         case Qremote:
102                 p = "remote";
103                 break;
104         case Qsnoop:
105                 if(strcmp(cv->p->name, "ipifc") != 0)
106                         return -1;
107                 devdir(c, q, "snoop", qlen(cv->sq), cv->owner, 0400, dp);
108                 return 1;
109         case Qstatus:
110                 p = "status";
111                 break;
112         }
113         devdir(c, q, p, 0, cv->owner, 0444, dp);
114         return 1;
115 }
116
117 static int
118 ip2gen(struct chan *c, int i, struct dir *dp)
119 {
120         struct qid q;
121
122         switch(i) {
123         case Qclone:
124                 mkqid(&q, QID(PROTO(c->qid), 0, Qclone), 0, QTFILE);
125                 devdir(c, q, "clone", 0, network, 0666, dp);
126                 return 1;
127         case Qstats:
128                 mkqid(&q, QID(PROTO(c->qid), 0, Qstats), 0, QTFILE);
129                 devdir(c, q, "stats", 0, network, 0444, dp);
130                 return 1;
131         }       
132         return -1;
133 }
134
135 static int
136 ip1gen(struct chan *c, int i, struct dir *dp)
137 {
138         struct qid q;
139         char *p;
140         int prot;
141         int len = 0;
142         struct Fs *f;
143         extern uint32_t kerndate;
144
145         f = ipfs[c->dev];
146
147         prot = 0666;
148         mkqid(&q, QID(0, 0, i), 0, QTFILE);
149         switch(i) {
150         default:
151                 return -1;
152         case Qarp:
153                 p = "arp";
154                 break;
155         case Qbootp:
156                 p = "bootp";
157                 if(bootp == NULL)
158                         return 0;
159                 break;
160         case Qndb:
161                 p = "ndb";
162                 len = strlen(f->ndb);
163                 q.vers = f->ndbvers;
164                 break;
165         case Qiproute:
166                 p = "iproute";
167                 break;
168         case Qipselftab:
169                 p = "ipselftab";
170                 prot = 0444;
171                 break;
172         case Qiprouter:
173                 p = "iprouter";
174                 break;
175         case Qlog:
176                 p = "log";
177                 break;
178         }
179         devdir(c, q, p, len, network, prot, dp);
180         if(i == Qndb && f->ndbmtime > kerndate)
181                 dp->mtime = f->ndbmtime;
182         return 1;
183 }
184
185 static int
186 ipgen(struct chan *c, char *unused_char_p_t, struct dirtab*d, int unused_int, int s, struct dir *dp)
187 {
188         struct qid q;
189         struct conv *cv;
190         struct Fs *f;
191
192         f = ipfs[c->dev];
193
194         switch(TYPE(c->qid)) {
195         case Qtopdir:
196                 if(s == DEVDOTDOT){
197                         mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR);
198                         snprintf(get_cur_genbuf(), GENBUF_SZ, "#I%lu", c->dev);
199                         devdir(c, q, get_cur_genbuf(), 0, network, 0555, dp);
200                         return 1;
201                 }
202                 if(s < f->np) {
203                         if(f->p[s]->connect == NULL)
204                                 return 0;       /* protocol with no user interface */
205                         mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR);
206                         devdir(c, q, f->p[s]->name, 0, network, 0555, dp);
207                         return 1;
208                 }
209                 s -= f->np;
210                 return ip1gen(c, s+Qtopbase, dp);
211         case Qarp:
212         case Qbootp:
213         case Qndb:
214         case Qlog:
215         case Qiproute:
216         case Qiprouter:
217         case Qipselftab:
218                 return ip1gen(c, TYPE(c->qid), dp);
219         case Qprotodir:
220                 if(s == DEVDOTDOT){
221                         mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR);
222                         snprintf(get_cur_genbuf(), GENBUF_SZ, "#I%lu", c->dev);
223                         devdir(c, q, get_cur_genbuf(), 0, network, 0555, dp);
224                         return 1;
225                 }
226                 if(s < f->p[PROTO(c->qid)]->ac) {
227                         cv = f->p[PROTO(c->qid)]->conv[s];
228                         snprintf(get_cur_genbuf(), GENBUF_SZ, "%d", s);
229                         mkqid(&q, QID(PROTO(c->qid), s, Qconvdir), 0, QTDIR);
230                         devdir(c, q, get_cur_genbuf(), 0, cv->owner, 0555, dp);
231                         return 1;
232                 }
233                 s -= f->p[PROTO(c->qid)]->ac;
234                 return ip2gen(c, s+Qprotobase, dp);
235         case Qclone:
236         case Qstats:
237                 return ip2gen(c, TYPE(c->qid), dp);
238         case Qconvdir:
239                 if(s == DEVDOTDOT){
240                         s = PROTO(c->qid);
241                         mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR);
242                         devdir(c, q, f->p[s]->name, 0, network, 0555, dp);
243                         return 1;
244                 }
245                 return ip3gen(c, s+Qconvbase, dp);
246         case Qctl:
247         case Qdata:
248         case Qerr:
249         case Qlisten:
250         case Qlocal:
251         case Qremote:
252         case Qstatus:
253         case Qsnoop:
254                 return ip3gen(c, TYPE(c->qid), dp);
255         }
256         return -1;
257 }
258
259 static void
260 ipinit(void)
261 {
262         qlock_init(&fslock);
263         nullmediumlink();
264         pktmediumlink();
265 /* if only
266         fmtinstall('i', eipfmt);
267         fmtinstall('I', eipfmt);
268         fmtinstall('E', eipfmt);
269         fmtinstall('V', eipfmt);
270         fmtinstall('M', eipfmt);
271 */
272 }
273
274 static void
275 ipreset(void)
276 {
277 }
278
279 static struct Fs*
280 ipgetfs(int dev)
281 {
282         extern void (*ipprotoinit[])(struct Fs*);
283         struct Fs *f;
284         int i;
285
286         if(dev >= Nfs)
287                 return NULL;
288
289         qlock(&fslock);
290         if(ipfs[dev] == NULL){
291                 f = kzmalloc(sizeof(struct Fs), KMALLOC_WAIT);
292                 rwinit(&f->rwlock);
293                 qlock_init(&f->iprouter.qlock);
294                 ip_init(f);
295                 arpinit(f);
296                 netloginit(f);
297                 for(i = 0; ipprotoinit[i]; i++)
298                         ipprotoinit[i](f);
299                 f->dev = dev;
300                 ipfs[dev] = f;
301         }
302         qunlock(&fslock);
303
304         return ipfs[dev];
305 }
306
307 struct IPaux*
308 newipaux(char *owner, char *tag)
309 {
310         struct IPaux *a;
311         int n;
312
313         a = kzmalloc(sizeof(*a), 0);
314         kstrdup(&a->owner, owner);
315         memset(a->tag, ' ', sizeof(a->tag));
316         n = strlen(tag);
317         if(n > sizeof(a->tag))
318                 n = sizeof(a->tag);
319         memmove(a->tag, tag, n);
320         return a;
321 }
322
323 #define ATTACHER(c) (((struct IPaux*)((c)->aux))->owner)
324
325 static struct chan*
326 ipattach(char* spec)
327 {
328         struct chan *c;
329         int dev;
330
331         dev = atoi(spec);
332         if(dev >= Nfs)
333                 error("bad specification");
334
335         ipgetfs(dev);
336         c = devattach('I', spec);
337         mkqid(&c->qid, QID(0, 0, Qtopdir), 0, QTDIR);
338         c->dev = dev;
339
340         c->aux = newipaux(commonuser(), "none");
341
342         return c;
343 }
344
345 static struct walkqid*
346 ipwalk(struct chan* c, struct chan *nc, char **name, int nname)
347 {
348         struct IPaux *a = c->aux;
349         struct walkqid* w;
350
351         w = devwalk(c, nc, name, nname, NULL, 0, ipgen);
352         if(w != NULL && w->clone != NULL)
353                 w->clone->aux = newipaux(a->owner, a->tag);
354         return w;
355 }
356
357 static int
358 ipstat(struct chan* c, uint8_t* db, int n)
359 {
360         return devstat(c, db, n, NULL, 0, ipgen);
361 }
362
363 static int
364 incoming(void* arg)
365 {
366         struct conv *conv;
367
368         conv = arg;
369         return conv->incall != NULL;
370 }
371
372 static int m2p[] = {
373         [OREAD]         4,
374         [OWRITE]        2,
375         [ORDWR]         6
376 };
377
378 static struct chan*
379 ipopen(struct chan* c, int omode)
380 {
381         ERRSTACK(2);
382         struct conv *cv, *nc;
383         struct Proto *p;
384         int perm;
385         struct Fs *f;
386
387         perm = m2p[omode&3];
388
389         f = ipfs[c->dev];
390
391         switch(TYPE(c->qid)) {
392         default:
393                 break;
394         case Qndb:
395                 if(omode & (OWRITE|OTRUNC) && !iseve())
396                         error(Eperm);
397                 if((omode & (OWRITE|OTRUNC)) == (OWRITE|OTRUNC))
398                         f->ndb[0] = 0;
399                 break;
400         case Qlog:
401                 netlogopen(f);
402                 break;
403         case Qiprouter:
404                 iprouteropen(f);
405                 break;
406         case Qiproute:
407                 break;
408         case Qtopdir:
409         case Qprotodir:
410         case Qconvdir:
411         case Qstatus:
412         case Qremote:
413         case Qlocal:
414         case Qstats:
415         case Qbootp:
416         case Qipselftab:
417                 if (!IS_RDONLY(omode))
418                         error(Eperm);
419                 break;
420         case Qsnoop:
421                 if (!IS_RDONLY(omode))
422                         error(Eperm);
423                 p = f->p[PROTO(c->qid)];
424                 cv = p->conv[CONV(c->qid)];
425                 if(strcmp(ATTACHER(c), cv->owner) != 0 && !iseve())
426                         error(Eperm);
427                 atomic_inc(&cv->snoopers);
428                 break;
429         case Qclone:
430                 p = f->p[PROTO(c->qid)];
431                 qlock(&p->qlock);
432                 if(waserror()){
433                         qunlock(&p->qlock);
434                         nexterror();
435                 }
436                 cv = Fsprotoclone(p, ATTACHER(c));
437                 qunlock(&p->qlock);
438                 poperror();
439                 if(cv == NULL) {
440                         error(Enodev);
441                         break;
442                 }
443                 mkqid(&c->qid, QID(p->x, cv->x, Qctl), 0, QTFILE);
444                 break;
445         case Qdata:
446         case Qctl:
447         case Qerr:
448                 p = f->p[PROTO(c->qid)];
449                 qlock(&p->qlock);
450                 cv = p->conv[CONV(c->qid)];
451                 qlock(&cv->qlock);
452                 if(waserror()) {
453                         qunlock(&cv->qlock);
454                         qunlock(&p->qlock);
455                         nexterror();
456                 }
457                 if((perm & (cv->perm>>6)) != perm) {
458                         if(strcmp(ATTACHER(c), cv->owner) != 0)
459                                 error(Eperm);
460                         if((perm & cv->perm) != perm)
461                                 error(Eperm); 
462
463                 }
464                 cv->inuse++;
465                 if(cv->inuse == 1){
466                         kstrdup(&cv->owner, ATTACHER(c));
467                         cv->perm = 0660;
468                 }
469                 qunlock(&cv->qlock);
470                 qunlock(&p->qlock);
471                 poperror();
472                 break;
473         case Qlisten:
474                 cv = f->p[PROTO(c->qid)]->conv[CONV(c->qid)];
475                 if((perm & (cv->perm>>6)) != perm) {
476                         if(strcmp(ATTACHER(c), cv->owner) != 0)
477                                 error(Eperm);
478                         if((perm & cv->perm) != perm)
479                                 error(Eperm); 
480
481                 }
482
483                 if(cv->state != Announced)
484                         error("not announced");
485
486                 if(waserror()){
487                         closeconv(cv);
488                         nexterror();
489                 }
490                 qlock(&cv->qlock);
491                 cv->inuse++;
492                 qunlock(&cv->qlock);
493
494                 nc = NULL;
495                 while(nc == NULL) {
496                         /* give up if we got a hangup */
497                         if(qisclosed(cv->rq))
498                                 error("listen hungup");
499
500                         qlock(&cv->listenq);
501                         if(waserror()) {
502                                 qunlock(&cv->listenq);
503                                 nexterror();
504                         }
505
506                         /* wait for a connect */
507                         rendez_sleep(&cv->listenr, incoming, cv);
508
509                         qlock(&cv->qlock);
510                         nc = cv->incall;
511                         if(nc != NULL){
512                                 cv->incall = nc->next;
513                                 mkqid(&c->qid, QID(PROTO(c->qid), nc->x, Qctl), 0, QTFILE);
514                                 kstrdup(&cv->owner, ATTACHER(c));
515                         }
516                         qunlock(&cv->qlock);
517
518                         qunlock(&cv->listenq);
519                         poperror();
520                 }
521                 closeconv(cv);
522                 poperror();
523                 break;
524         }
525         c->mode = openmode(omode);
526         c->flag |= COPEN;
527         c->offset = 0;
528         return c;
529 }
530
531 static int
532 ipwstat(struct chan *c, uint8_t *dp, int n)
533 {
534         ERRSTACK(2);
535         struct dir *d;
536         struct conv *cv;
537         struct Fs *f;
538         struct Proto *p;
539
540         f = ipfs[c->dev];
541         switch(TYPE(c->qid)) {
542         default:
543                 error(Eperm);
544                 break;
545         case Qctl:
546         case Qdata:
547                 break;
548         }
549
550         d = kzmalloc(sizeof(*d) + n, 0);
551         if(waserror()){
552                 kfree(d);
553                 nexterror();
554         }
555         n = convM2D(dp, n, d, ( char *)&d[1]);
556         if(n == 0)
557                 error(Eshortstat);
558         p = f->p[PROTO(c->qid)];
559         cv = p->conv[CONV(c->qid)];
560         if(!iseve() && strcmp(ATTACHER(c), cv->owner) != 0)
561                 error(Eperm);
562         if(!emptystr(d->uid))
563                 kstrdup(&cv->owner, d->uid);
564         if(d->mode != ~0UL)
565                 cv->perm = d->mode & 0777;
566         poperror();
567         kfree(d);
568         return n;
569 }
570
571 /* Should be able to handle any file type chan. Feel free to extend it. */
572 static char *ipchaninfo(struct chan *ch, char *ret, size_t ret_l)
573 {
574         struct conv *conv;
575         struct Proto *proto;
576         char *p;
577         struct Fs *f;
578         
579         f = ipfs[ch->dev];
580         
581         switch (TYPE(ch->qid)) {
582                 default:
583                         ret = "Unknown type";
584                         break;
585                 case Qdata:
586                         proto = f->p[PROTO(ch->qid)];
587                         conv = proto->conv[CONV(ch->qid)];
588                         snprintf(ret, ret_l, "Qdata, proto %s, conv idx %d", proto->name,
589                                  conv->x);
590                         break;
591                 case Qarp:
592                         ret = "Qarp";
593                         break;
594                 case Qiproute:
595                         ret = "Qiproute";
596                         break;
597                 case Qlog:
598                         ret = "Qlog";
599                         break;
600                 case Qndb:
601                         ret = "Qndb";
602                         break;
603                 case Qctl:
604                         proto = f->p[PROTO(ch->qid)];
605                         conv = proto->conv[CONV(ch->qid)];
606                         snprintf(ret, ret_l, "Qctl, proto %s, conv idx %d", proto->name,
607                                  conv->x);
608                         break;
609         }
610         return ret;
611 }
612
613 static void
614 closeconv(struct conv *cv)
615 {
616         struct conv *nc;
617         struct Ipmulti *mp;
618
619         qlock(&cv->qlock);
620
621         if(--cv->inuse > 0) {
622                 qunlock(&cv->qlock);
623                 return;
624         }
625
626         /* close all incoming calls since no listen will ever happen */
627         for(nc = cv->incall; nc; nc = cv->incall){
628                 cv->incall = nc->next;
629                 closeconv(nc);
630         }
631         cv->incall = NULL;
632
633         kstrdup(&cv->owner, network);
634         cv->perm = 0660;
635
636         while((mp = cv->multi) != NULL)
637                 ipifcremmulti(cv, mp->ma, mp->ia);
638
639         cv->r = NULL;
640         cv->rgen = 0;
641         cv->p->close(cv);
642         cv->state = Idle;
643         qunlock(&cv->qlock);
644 }
645
646 static void
647 ipclose(struct chan* c)
648 {
649         struct Fs *f;
650
651         f = ipfs[c->dev];
652         switch(TYPE(c->qid)) {
653         default:
654                 break;
655         case Qlog:
656                 if(c->flag & COPEN)
657                         netlogclose(f);
658                 break;
659         case Qiprouter:
660                 if(c->flag & COPEN)
661                         iprouterclose(f);
662                 break;
663         case Qdata:
664         case Qctl:
665         case Qerr:
666                 if(c->flag & COPEN)
667                         closeconv(f->p[PROTO(c->qid)]->conv[CONV(c->qid)]);
668                 break;
669         case Qsnoop:
670                 if(c->flag & COPEN)
671                         atomic_dec(&f->p[PROTO(c->qid)]->conv[CONV(c->qid)]->snoopers);
672                 break;
673         }
674         kfree(((struct IPaux*)c->aux)->owner);
675         kfree(c->aux);
676 }
677
678 enum
679 {
680         Statelen=       32*1024,
681 };
682
683 static long
684 ipread(struct chan *ch, void *a, long n, int64_t off)
685 {
686         struct conv *c;
687         struct Proto *x;
688         char *buf, *p;
689         long rv;
690         struct Fs *f;
691         uint32_t offset = off;
692
693         f = ipfs[ch->dev];
694
695         p = a;
696         switch(TYPE(ch->qid)) {
697         default:
698                 error(Eperm);
699         case Qtopdir:
700         case Qprotodir:
701         case Qconvdir:
702                 return devdirread(ch, a, n, 0, 0, ipgen);
703         case Qarp:
704                 return arpread(f->arp, a, offset, n);
705         case Qbootp:
706                 return bootpread(a, offset, n);
707         case Qndb:
708                 return readstr(offset, a, n, f->ndb);
709         case Qiproute:
710                 return routeread(f, a, offset, n);
711         case Qiprouter:
712                 return iprouterread(f, a, n);
713         case Qipselftab:
714                 return ipselftabread(f, a, offset, n);
715         case Qlog:
716                 return netlogread(f, a, offset, n);
717         case Qctl:
718                 snprintf(get_cur_genbuf(), GENBUF_SZ, "%lu", CONV(ch->qid));
719                 return readstr(offset, p, n, get_cur_genbuf());
720         case Qremote:
721                 buf = kzmalloc(Statelen, 0);
722                 x = f->p[PROTO(ch->qid)];
723                 c = x->conv[CONV(ch->qid)];
724                 if(x->remote == NULL) {
725                         snprintf(buf, Statelen, "%I!%d\n", c->raddr, c->rport);
726                 } else {
727                         (*x->remote)(c, buf, Statelen-2);
728                 }
729                 rv = readstr(offset, p, n, buf);
730                 kfree(buf);
731                 return rv;
732         case Qlocal:
733                 buf = kzmalloc(Statelen, 0);
734                 x = f->p[PROTO(ch->qid)];
735                 c = x->conv[CONV(ch->qid)];
736                 if(x->local == NULL) {
737                         snprintf(buf, Statelen, "%I!%d\n", c->laddr, c->lport);
738                 } else {
739                         (*x->local)(c, buf, Statelen-2);
740                 }
741                 rv = readstr(offset, p, n, buf);
742                 kfree(buf);
743                 return rv;
744         case Qstatus:
745                 buf = kzmalloc(Statelen, 0);
746                 x = f->p[PROTO(ch->qid)];
747                 c = x->conv[CONV(ch->qid)];
748                 (*x->state)(c, buf, Statelen-2);
749                 rv = readstr(offset, p, n, buf);
750                 kfree(buf);
751                 return rv;
752         case Qdata:
753                 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
754                 return qread(c->rq, a, n);
755         case Qerr:
756                 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
757                 return qread(c->eq, a, n);
758         case Qsnoop:
759                 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
760                 return qread(c->sq, a, n);
761         case Qstats:
762                 x = f->p[PROTO(ch->qid)];
763                 if(x->stats == NULL)
764                         error("stats not implemented");
765                 buf = kzmalloc(Statelen, 0);
766                 (*x->stats)(x, buf, Statelen);
767                 rv = readstr(offset, p, n, buf);
768                 kfree(buf);
769                 return rv;
770         }
771 }
772
773 static struct block*
774 ipbread(struct chan* ch, long n, uint32_t offset)
775 {
776         struct conv *c;
777         struct Proto *x;
778         struct Fs *f;
779
780         switch(TYPE(ch->qid)){
781         case Qdata:
782                 f = ipfs[ch->dev];
783                 x = f->p[PROTO(ch->qid)];
784                 c = x->conv[CONV(ch->qid)];
785                 return qbread(c->rq, n);
786         default:
787                 return devbread(ch, n, offset);
788         }
789 }
790
791 /*
792  *  set local address to be that of the ifc closest to remote address
793  */
794 static void
795 setladdr(struct conv* c)
796 {
797         findlocalip(c->p->f, c->laddr, c->raddr);
798 }
799
800 /*
801  *  set a local port making sure the quad of raddr,rport,laddr,lport is unique
802  */
803 static char*
804 setluniqueport(struct conv* c, int lport)
805 {
806         struct Proto *p;
807         struct conv *xp;
808         int x;
809
810         p = c->p;
811
812         qlock(&p->qlock);
813         for(x = 0; x < p->nc; x++){
814                 xp = p->conv[x];
815                 if(xp == NULL)
816                         break;
817                 if(xp == c)
818                         continue;
819                 if((xp->state == Connected || xp->state == Announced)
820                 && xp->lport == lport
821                 && xp->rport == c->rport
822                 && ipcmp(xp->raddr, c->raddr) == 0
823                 && ipcmp(xp->laddr, c->laddr) == 0){
824                         qunlock(&p->qlock);
825                         return "address in use";
826                 }
827         }
828         c->lport = lport;
829         qunlock(&p->qlock);
830         return NULL;
831 }
832
833 /*
834  *  pick a local port and set it
835  */
836 static void
837 setlport(struct conv* c)
838 {
839         struct Proto *p;
840         uint16_t *pp;
841         int x, found;
842
843         p = c->p;
844         if(c->restricted)
845                 pp = &p->nextrport;
846         else
847                 pp = &p->nextport;
848         qlock(&p->qlock);
849         for(;;(*pp)++){
850                 /*
851                  * Fsproto initialises p->nextport to 0 and the restricted
852                  * ports (p->nextrport) to 600.
853                  * Restricted ports must lie between 600 and 1024.
854                  * For the initial condition or if the unrestricted port number
855                  * has wrapped round, select a random port between 5000 and 1<<15
856                  * to start at.
857                  */
858                 if(c->restricted){
859                         if(*pp >= 1024)
860                                 *pp = 600;
861                 }
862                 else while(*pp < 5000)
863                         *pp = nrand(1<<15);
864
865                 found = 0;
866                 for(x = 0; x < p->nc; x++){
867                         if(p->conv[x] == NULL)
868                                 break;
869                         if(p->conv[x]->lport == *pp){
870                                 found = 1;
871                                 break;
872                         }
873                 }
874                 if(!found)
875                         break;
876         }
877         c->lport = (*pp)++;
878         qunlock(&p->qlock);
879 }
880
881 /*
882  *  set a local address and port from a string of the form
883  *      [address!]port[!r]
884  */
885 static char*
886 setladdrport(struct conv* c, char* str, int announcing)
887 {
888         char *p;
889         char *rv;
890         uint16_t lport;
891         uint8_t addr[IPaddrlen];
892
893         rv = NULL;
894
895         /*
896          *  ignore restricted part if it exists.  it's
897          *  meaningless on local ports.
898          */
899         p = strchr(str, '!');
900         if(p != NULL){
901                 *p++ = 0;
902                 if(strcmp(p, "r") == 0)
903                         p = NULL;
904         }
905
906         c->lport = 0;
907         if(p == NULL){
908                 if(announcing)
909                         ipmove(c->laddr, IPnoaddr);
910                 else
911                         setladdr(c);
912                 p = str;
913         } else {
914                 if(strcmp(str, "*") == 0)
915                         ipmove(c->laddr, IPnoaddr);
916                 else {
917                         parseip(addr, str);
918                         if(ipforme(c->p->f, addr))
919                                 ipmove(c->laddr, addr);
920                         else
921                                 return "not a local IP address";
922                 }
923         }
924
925         /* one process can get all connections */
926         if(announcing && strcmp(p, "*") == 0){
927                 if(!iseve())
928                         error(Eperm);
929                 return setluniqueport(c, 0);
930         }
931
932         lport = atoi(p);
933         if(lport <= 0)
934                 setlport(c);
935         else
936                 rv = setluniqueport(c, lport);
937         return rv;
938 }
939
940 static char*
941 setraddrport(struct conv* c, char* str)
942 {
943         char *p;
944
945         p = strchr(str, '!');
946         if(p == NULL)
947                 return "malformed address";
948         *p++ = 0;
949         parseip(c->raddr, str);
950         c->rport = atoi(p);
951         p = strchr(p, '!');
952         if(p){
953                 if(strstr(p, "!r") != NULL)
954                         c->restricted = 1;
955         }
956         return NULL;
957 }
958
959 /*
960  *  called by protocol connect routine to set addresses
961  */
962 char*
963 Fsstdconnect(struct conv *c, char *argv[], int argc)
964 {
965         char *p;
966
967         switch(argc) {
968         default:
969                 return "bad args to connect";
970         case 2:
971                 p = setraddrport(c, argv[1]);
972                 if(p != NULL)
973                         return p;
974                 setladdr(c);
975                 setlport(c);
976                 break;
977         case 3:
978                 p = setraddrport(c, argv[1]);
979                 if(p != NULL)
980                         return p;
981                 p = setladdrport(c, argv[2], 0);
982                 if(p != NULL)
983                         return p;
984         }
985
986         if((memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
987                 memcmp(c->laddr, v4prefix, IPv4off) == 0)
988                 || ipcmp(c->raddr, IPnoaddr) == 0)
989                 c->ipversion = V4;
990         else
991                 c->ipversion = V6;
992
993         return NULL;
994 }
995 /*
996  *  initiate connection and sleep till its set up
997  */
998 static int
999 connected(void* a)
1000 {
1001         return ((struct conv*)a)->state == Connected;
1002 }
1003 static void
1004 connectctlmsg(struct Proto *x, struct conv *c, struct cmdbuf *cb)
1005 {
1006         ERRSTACK(1);
1007         char *p;
1008
1009         if(c->state != 0)
1010                 error(Econinuse);
1011         c->state = Connecting;
1012         c->cerr[0] = '\0';
1013         if(x->connect == NULL)
1014                 error("connect not supported");
1015         p = x->connect(c, cb->f, cb->nf);
1016         if(p != NULL)
1017                 error(p);
1018
1019         qunlock(&c->qlock);
1020         if(waserror()){
1021                 qlock(&c->qlock);
1022                 nexterror();
1023         }
1024         rendez_sleep(&c->cr, connected, c);
1025         qlock(&c->qlock);
1026         poperror();
1027
1028         if(c->cerr[0] != '\0')
1029                 error(c->cerr);
1030 }
1031
1032 /*
1033  *  called by protocol announce routine to set addresses
1034  */
1035 char*
1036 Fsstdannounce(struct conv* c, char* argv[], int argc)
1037 {
1038         memset(c->raddr, 0, sizeof(c->raddr));
1039         c->rport = 0;
1040         switch(argc){
1041         default:
1042                 return "bad args to announce";
1043         case 2:
1044                 return setladdrport(c, argv[1], 1);
1045         }
1046 }
1047
1048 /*
1049  *  initiate announcement and sleep till its set up
1050  */
1051 static int
1052 announced(void* a)
1053 {
1054         return ((struct conv*)a)->state == Announced;
1055 }
1056 static void
1057 announcectlmsg(struct Proto *x, struct conv *c, struct cmdbuf *cb)
1058 {
1059         ERRSTACK(1);
1060         char *p;
1061
1062         if(c->state != 0)
1063                 error(Econinuse);
1064         c->state = Announcing;
1065         c->cerr[0] = '\0';
1066         if(x->announce == NULL)
1067                 error("announce not supported");
1068         p = x->announce(c, cb->f, cb->nf);
1069         if(p != NULL)
1070                 error(p);
1071
1072         qunlock(&c->qlock);
1073         if(waserror()){
1074                 qlock(&c->qlock);
1075                 nexterror();
1076         }
1077         rendez_sleep(&c->cr, announced, c);
1078         qlock(&c->qlock);
1079         poperror();
1080
1081         if(c->cerr[0] != '\0')
1082                 error(c->cerr);
1083 }
1084
1085 /*
1086  *  called by protocol bind routine to set addresses
1087  */
1088 char*
1089 Fsstdbind(struct conv* c, char* argv[], int argc)
1090 {
1091         switch(argc){
1092         default:
1093                 return "bad args to bind";
1094         case 2:
1095                 return setladdrport(c, argv[1], 0);
1096         }
1097 }
1098
1099 static void
1100 bindctlmsg(struct Proto *x, struct conv *c, struct cmdbuf *cb)
1101 {
1102         char *p;
1103
1104         if(x->bind == NULL)
1105                 p = Fsstdbind(c, cb->f, cb->nf);
1106         else
1107                 p = x->bind(c, cb->f, cb->nf);
1108         if(p != NULL)
1109                 error(p);
1110 }
1111
1112 static void
1113 tosctlmsg(struct conv *c, struct cmdbuf *cb)
1114 {
1115         if(cb->nf < 2)
1116                 c->tos = 0;
1117         else
1118                 c->tos = atoi(cb->f[1]);
1119 }
1120
1121 static void
1122 ttlctlmsg(struct conv *c, struct cmdbuf *cb)
1123 {
1124         if(cb->nf < 2)
1125                 c->ttl = MAXTTL;
1126         else
1127                 c->ttl = atoi(cb->f[1]);
1128 }
1129
1130 static long
1131 ipwrite(struct chan* ch, void *v, long n, int64_t off)
1132 {
1133         ERRSTACK(1);
1134         struct conv *c;
1135         struct Proto *x;
1136         char *p;
1137         struct cmdbuf *cb;
1138         uint8_t ia[IPaddrlen], ma[IPaddrlen];
1139         struct Fs *f;
1140         char *a;
1141
1142         a = v;
1143         f = ipfs[ch->dev];
1144
1145         switch(TYPE(ch->qid)){
1146         default:
1147                 error(Eperm);
1148         case Qdata:
1149                 x = f->p[PROTO(ch->qid)];
1150                 c = x->conv[CONV(ch->qid)];
1151
1152                 if(c->wq == NULL)
1153                         error(Eperm);
1154
1155                 qwrite(c->wq, a, n);
1156                 break;
1157         case Qarp:
1158                 return arpwrite(f, a, n);
1159         case Qiproute:
1160                 return routewrite(f, ch, a, n);
1161         case Qlog:
1162                 netlogctl(f, a, n);
1163                 return n;
1164         case Qndb:
1165                 return ndbwrite(f, a, off, n);
1166         case Qctl:
1167                 x = f->p[PROTO(ch->qid)];
1168                 c = x->conv[CONV(ch->qid)];
1169                 cb = parsecmd(a, n);
1170
1171                 qlock(&c->qlock);
1172                 if(waserror()) {
1173                         qunlock(&c->qlock);
1174                         kfree(cb);
1175                         nexterror();
1176                 }
1177                 if(cb->nf < 1)
1178                         error("short control request");
1179                 if(strcmp(cb->f[0], "connect") == 0)
1180                         connectctlmsg(x, c, cb);
1181                 else if(strcmp(cb->f[0], "announce") == 0)
1182                         announcectlmsg(x, c, cb);
1183                 else if(strcmp(cb->f[0], "bind") == 0)
1184                         bindctlmsg(x, c, cb);
1185                 else if(strcmp(cb->f[0], "ttl") == 0)
1186                         ttlctlmsg(c, cb);
1187                 else if(strcmp(cb->f[0], "tos") == 0)
1188                         tosctlmsg(c, cb);
1189                 else if(strcmp(cb->f[0], "ignoreadvice") == 0)
1190                         c->ignoreadvice = 1;
1191                 else if(strcmp(cb->f[0], "addmulti") == 0){
1192                         if(cb->nf < 2)
1193                                 error("addmulti needs interface address");
1194                         if(cb->nf == 2){
1195                                 if(!ipismulticast(c->raddr))
1196                                         error("addmulti for a non multicast address");
1197                                 parseip(ia, cb->f[1]);
1198                                 ipifcaddmulti(c, c->raddr, ia);
1199                         } else {
1200                                 parseip(ma, cb->f[2]);
1201                                 if(!ipismulticast(ma))
1202                                         error("addmulti for a non multicast address");
1203                                 parseip(ia, cb->f[1]);
1204                                 ipifcaddmulti(c, ma, ia);
1205                         }
1206                 } else if(strcmp(cb->f[0], "remmulti") == 0){
1207                         if(cb->nf < 2)
1208                                 error("remmulti needs interface address");
1209                         if(!ipismulticast(c->raddr))
1210                                 error("remmulti for a non multicast address");
1211                         parseip(ia, cb->f[1]);
1212                         ipifcremmulti(c, c->raddr, ia);
1213                 } else if(x->ctl != NULL) {
1214                         p = x->ctl(c, cb->f, cb->nf);
1215                         if(p != NULL)
1216                                 error(p);
1217                 } else
1218                         error("unknown control request");
1219                 qunlock(&c->qlock);
1220                 kfree(cb);
1221                 poperror();
1222         }
1223         return n;
1224 }
1225
1226 static long
1227 ipbwrite(struct chan* ch, struct block* bp, uint32_t offset)
1228 {
1229         struct conv *c;
1230         struct Proto *x;
1231         struct Fs *f;
1232         int n;
1233
1234         switch(TYPE(ch->qid)){
1235         case Qdata:
1236                 f = ipfs[ch->dev];
1237                 x = f->p[PROTO(ch->qid)];
1238                 c = x->conv[CONV(ch->qid)];
1239
1240                 if(c->wq == NULL)
1241                         error(Eperm);
1242
1243                 if(bp->next)
1244                         bp = concatblock(bp);
1245                 n = BLEN(bp);
1246                 qbwrite(c->wq, bp);
1247                 return n;
1248         default:
1249                 return devbwrite(ch, bp, offset);
1250         }
1251 }
1252
1253 struct dev ipdevtab __devtab = {
1254         'I',
1255         "ip",
1256
1257         ipreset,
1258         ipinit,
1259         devshutdown,
1260         ipattach,
1261         ipwalk,
1262         ipstat,
1263         ipopen,
1264         devcreate,
1265         ipclose,
1266         ipread,
1267         ipbread,
1268         ipwrite,
1269         ipbwrite,
1270         devremove,
1271         ipwstat,
1272         devpower,
1273         ipchaninfo,
1274 };
1275
1276 int
1277 Fsproto(struct Fs *f, struct Proto *p)
1278 {
1279         if(f->np >= Maxproto)
1280                 return -1;
1281
1282         qlock_init(&p->qlock);
1283         p->f = f;
1284
1285         if(p->ipproto > 0){
1286                 if(f->t2p[p->ipproto] != NULL)
1287                         return -1;
1288                 f->t2p[p->ipproto] = p;
1289         }
1290
1291         p->qid.type = QTDIR;
1292         p->qid.path = QID(f->np, 0, Qprotodir);
1293         p->conv = kzmalloc(sizeof(struct conv *) * (p->nc + 1), 0);
1294         if(p->conv == NULL)
1295                 panic("Fsproto");
1296
1297         p->x = f->np;
1298         p->nextport = 0;
1299         p->nextrport = 600;
1300         f->p[f->np++] = p;
1301
1302         return 0;
1303 }
1304
1305 /*
1306  *  return true if this protocol is
1307  *  built in
1308  */
1309 int
1310 Fsbuiltinproto(struct Fs* f, uint8_t proto)
1311 {
1312         return f->t2p[proto] != NULL;
1313 }
1314
1315 /*
1316  *  called with protocol locked
1317  */
1318 struct conv*
1319 Fsprotoclone(struct Proto *p, char *user)
1320 {
1321         struct conv *c, **pp, **ep;
1322
1323 retry:
1324         c = NULL;
1325         ep = &p->conv[p->nc];
1326         for(pp = p->conv; pp < ep; pp++) {
1327                 c = *pp;
1328                 if(c == NULL){
1329                         c = kzmalloc(sizeof(struct conv), 0);
1330                         if(c == NULL)
1331                                 error(Enomem);
1332                         qlock_init(&c->qlock);
1333                         qlock_init(&c->listenq);
1334                         rendez_init(&c->cr);
1335                         rendez_init(&c->listenr);
1336                         qlock(&c->qlock);
1337                         c->p = p;
1338                         c->x = pp - p->conv;
1339                         if(p->ptclsize != 0){
1340                                 c->ptcl = kzmalloc(p->ptclsize, 0);
1341                                 if(c->ptcl == NULL) {
1342                                         kfree(c);
1343                                         error(Enomem);
1344                                 }
1345                         }
1346                         *pp = c;
1347                         p->ac++;
1348                         c->eq = qopen(1024, Qmsg, 0, 0);
1349                         (*p->create)(c);
1350                         break;
1351                 }
1352                 if(canqlock(&c->qlock)){
1353                         /*
1354                          *  make sure both processes and protocol
1355                          *  are done with this Conv
1356                          */
1357                         if(c->inuse == 0 && (p->inuse == NULL || (*p->inuse)(c) == 0))
1358                                 break;
1359
1360                         qunlock(&c->qlock);
1361                 }
1362         }
1363         if(pp >= ep) {
1364                 if(p->gc != NULL && (*p->gc)(p))
1365                         goto retry;
1366                 return NULL;
1367         }
1368
1369         c->inuse = 1;
1370         kstrdup(&c->owner, user);
1371         c->perm = 0660;
1372         c->state = Idle;
1373         ipmove(c->laddr, IPnoaddr);
1374         ipmove(c->raddr, IPnoaddr);
1375         c->r = NULL;
1376         c->rgen = 0;
1377         c->lport = 0;
1378         c->rport = 0;
1379         c->restricted = 0;
1380         c->ttl = MAXTTL;
1381         c->tos = DFLTTOS;
1382         qreopen(c->rq);
1383         qreopen(c->wq);
1384         qreopen(c->eq);
1385
1386         qunlock(&c->qlock);
1387         return c;
1388 }
1389
1390 int
1391 Fsconnected(struct conv* c, char* msg)
1392 {
1393         if(msg != NULL && *msg != '\0')
1394                 strncpy(c->cerr, msg, sizeof(c->cerr));
1395
1396         switch(c->state){
1397
1398         case Announcing:
1399                 c->state = Announced;
1400                 break;
1401
1402         case Connecting:
1403                 c->state = Connected;
1404                 break;
1405         }
1406
1407         rendez_wakeup(&c->cr);
1408         return 0;
1409 }
1410
1411 struct Proto*
1412 Fsrcvpcol(struct Fs* f, uint8_t proto)
1413 {
1414         if(f->ipmux)
1415                 return f->ipmux;
1416         else
1417                 return f->t2p[proto];
1418 }
1419
1420 struct Proto*
1421 Fsrcvpcolx(struct Fs *f, uint8_t proto)
1422 {
1423         return f->t2p[proto];
1424 }
1425
1426 /*
1427  *  called with protocol locked
1428  */
1429 struct conv*
1430 Fsnewcall(struct conv *c, uint8_t *raddr, uint16_t rport, uint8_t *laddr,
1431           uint16_t lport, uint8_t version)
1432 {
1433         struct conv *nc;
1434         struct conv **l;
1435         int i;
1436
1437         qlock(&c->qlock);
1438         i = 0;
1439         for(l = &c->incall; *l; l = &(*l)->next)
1440                 i++;
1441         if(i >= Maxincall) {
1442                 qunlock(&c->qlock);
1443                 return NULL;
1444         }
1445
1446         /* find a free conversation */
1447         nc = Fsprotoclone(c->p, network);
1448         if(nc == NULL) {
1449                 qunlock(&c->qlock);
1450                 return NULL;
1451         }
1452         ipmove(nc->raddr, raddr);
1453         nc->rport = rport;
1454         ipmove(nc->laddr, laddr);
1455         nc->lport = lport;
1456         nc->next = NULL;
1457         *l = nc;
1458         nc->state = Connected;
1459         nc->ipversion = version;
1460
1461         qunlock(&c->qlock);
1462
1463         rendez_wakeup(&c->listenr);
1464
1465         return nc;
1466 }
1467
1468 static long
1469 ndbwrite(struct Fs *f, char *a, uint32_t off, int n)
1470 {
1471         if(off > strlen(f->ndb))
1472                 error(Eio);
1473         if(off+n >= sizeof(f->ndb)-1)
1474                 error(Eio);
1475         memmove(f->ndb+off, a, n);
1476         f->ndb[off+n] = 0;
1477         f->ndbvers++;
1478         f->ndbmtime = seconds();
1479         return n;
1480 }
1481
1482 uint32_t
1483 scalednconv(void)
1484 {
1485         //if(conf.npage*BY2PG >= 128*MB)
1486                 return Nchans*4;
1487                 //      return Nchans;
1488 }