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