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