Fix devip's permission conversion
[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 inline int founddevdir(struct chan *c, struct qid q, char *n,
71                                                           int64_t length, char *user, long perm,
72                                                           struct dir *db)
73 {
74         devdir(c, q, n, length, user, perm, db);
75         return 1;
76 }
77
78 static int topdirgen(struct chan *c, struct dir *dp)
79 {
80         struct qid q;
81         mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR);
82         snprintf(get_cur_genbuf(), GENBUF_SZ, "#I%lu", c->dev);
83         return founddevdir(c, q, get_cur_genbuf(), 0, network, 0555, dp);
84 }
85
86
87 static int ip3gen(struct chan *c, int i, struct dir *dp)
88 {
89         struct qid q;
90         struct conv *cv;
91         char *p;
92
93         cv = ipfs[c->dev]->p[PROTO(c->qid)]->conv[CONV(c->qid)];
94         if (cv->owner == NULL)
95                 kstrdup(&cv->owner, eve);
96         mkqid(&q, QID(PROTO(c->qid), CONV(c->qid), i), 0, QTFILE);
97
98         switch (i) {
99                 default:
100                         return -1;
101                 case Qctl:
102                         return founddevdir(c, q, "ctl", 0,
103                                                    cv->owner, cv->perm, dp);
104                 case Qdata:
105                         return founddevdir(c, q, "data", qlen(cv->rq),
106                                                            cv->owner, cv->perm, dp);
107                 case Qerr:
108                         return founddevdir(c, q, "err", qlen(cv->eq),
109                                                            cv->owner, cv->perm, dp);
110                 case Qlisten:
111                         return founddevdir(c, q, "listen", 0, cv->owner, cv->perm, dp);
112                 case Qlocal:
113                         p = "local";
114                         break;
115                 case Qremote:
116                         p = "remote";
117                         break;
118                 case Qsnoop:
119                         if (strcmp(cv->p->name, "ipifc") != 0)
120                                 return -1;
121                         return founddevdir(c, q, "snoop", qlen(cv->sq),
122                                                            cv->owner, 0400, dp);
123                 case Qstatus:
124                         p = "status";
125                         break;
126         }
127         return founddevdir(c, q, p, 0, cv->owner, 0444, dp);
128 }
129
130 static int ip2gen(struct chan *c, int i, struct dir *dp)
131 {
132         struct qid q;
133         mkqid(&q, QID(PROTO(c->qid), 0, i), 0, QTFILE);
134         switch (i) {
135                 case Qclone:
136                         return founddevdir(c, q, "clone", 0, network, 0666, dp);
137                 case Qstats:
138                         return founddevdir(c, q, "stats", 0, network, 0444, dp);
139         }
140         return -1;
141 }
142
143 static int ip1gen(struct chan *c, int i, struct dir *dp)
144 {
145         struct qid q;
146         char *p;
147         int prot;
148         int len = 0;
149         struct Fs *f;
150         extern uint32_t kerndate;
151
152         f = ipfs[c->dev];
153
154         prot = 0666;
155         mkqid(&q, QID(0, 0, i), 0, QTFILE);
156         switch (i) {
157                 default:
158                         return -1;
159                 case Qarp:
160                         p = "arp";
161                         break;
162                 case Qbootp:
163                         if (bootp == NULL)
164                                 return 0;
165                         p = "bootp";
166                         break;
167                 case Qndb:
168                         p = "ndb";
169                         len = strlen(f->ndb);
170                         q.vers = f->ndbvers;
171                         break;
172                 case Qiproute:
173                         p = "iproute";
174                         break;
175                 case Qipselftab:
176                         p = "ipselftab";
177                         prot = 0444;
178                         break;
179                 case Qiprouter:
180                         p = "iprouter";
181                         break;
182                 case Qlog:
183                         p = "log";
184                         break;
185         }
186         devdir(c, q, p, len, network, prot, dp);
187         if (i == Qndb && f->ndbmtime > kerndate)
188                 dp->mtime = f->ndbmtime;
189         return 1;
190 }
191
192 static int
193 ipgen(struct chan *c, char *unused_char_p_t, struct dirtab *d, int unused_int,
194           int s, struct dir *dp)
195 {
196         struct qid q;
197         struct conv *cv;
198         struct Fs *f;
199
200         f = ipfs[c->dev];
201
202         switch (TYPE(c->qid)) {
203                 case Qtopdir:
204                         if (s == DEVDOTDOT)
205                                 return topdirgen(c, dp);
206                         if (s < f->np) {
207                                 if (f->p[s]->connect == NULL)
208                                         return 0;       /* protocol with no user interface */
209                                 mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR);
210                                 return founddevdir(c, q, f->p[s]->name, 0, network, 0555, dp);
211                         }
212                         s -= f->np;
213                         return ip1gen(c, s + Qtopbase, dp);
214                 case Qarp:
215                 case Qbootp:
216                 case Qndb:
217                 case Qlog:
218                 case Qiproute:
219                 case Qiprouter:
220                 case Qipselftab:
221                         return ip1gen(c, TYPE(c->qid), dp);
222                 case Qprotodir:
223                         if (s == DEVDOTDOT)
224                                 return topdirgen(c, dp);
225                         else if (s < f->p[PROTO(c->qid)]->ac) {
226                                 cv = f->p[PROTO(c->qid)]->conv[s];
227                                 snprintf(get_cur_genbuf(), GENBUF_SZ, "%d", s);
228                                 mkqid(&q, QID(PROTO(c->qid), s, Qconvdir), 0, QTDIR);
229                                 return
230                                         founddevdir(c, q, get_cur_genbuf(), 0, cv->owner, 0555, dp);
231                         }
232                         s -= f->p[PROTO(c->qid)]->ac;
233                         return ip2gen(c, s + Qprotobase, dp);
234                 case Qclone:
235                 case Qstats:
236                         return ip2gen(c, TYPE(c->qid), dp);
237                 case Qconvdir:
238                         if (s == DEVDOTDOT) {
239                                 s = PROTO(c->qid);
240                                 mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR);
241                                 devdir(c, q, f->p[s]->name, 0, network, 0555, dp);
242                                 return 1;
243                         }
244                         return ip3gen(c, s + Qconvbase, dp);
245                 case Qctl:
246                 case Qdata:
247                 case Qerr:
248                 case Qlisten:
249                 case Qlocal:
250                 case Qremote:
251                 case Qstatus:
252                 case Qsnoop:
253                         return ip3gen(c, TYPE(c->qid), dp);
254         }
255         return -1;
256 }
257
258 static void ipinit(void)
259 {
260         qlock_init(&fslock);
261         nullmediumlink();
262         pktmediumlink();
263 /* if only
264         fmtinstall('i', eipfmt);
265         fmtinstall('I', eipfmt);
266         fmtinstall('E', eipfmt);
267         fmtinstall('V', eipfmt);
268         fmtinstall('M', eipfmt);
269 */
270 }
271
272 static void ipreset(void)
273 {
274 }
275
276 static struct Fs *ipgetfs(int dev)
277 {
278         extern void (*ipprotoinit[]) (struct Fs *);
279         struct Fs *f;
280         int i;
281
282         if (dev >= Nfs)
283                 return NULL;
284
285         qlock(&fslock);
286         if (ipfs[dev] == NULL) {
287                 f = kzmalloc(sizeof(struct Fs), KMALLOC_WAIT);
288                 rwinit(&f->rwlock);
289                 qlock_init(&f->iprouter.qlock);
290                 ip_init(f);
291                 arpinit(f);
292                 netloginit(f);
293                 for (i = 0; ipprotoinit[i]; i++)
294                         ipprotoinit[i] (f);
295                 f->dev = dev;
296                 ipfs[dev] = f;
297         }
298         qunlock(&fslock);
299
300         return ipfs[dev];
301 }
302
303 struct IPaux *newipaux(char *owner, char *tag)
304 {
305         struct IPaux *a;
306         int n;
307
308         a = kzmalloc(sizeof(*a), 0);
309         kstrdup(&a->owner, owner);
310         memset(a->tag, ' ', sizeof(a->tag));
311         n = strlen(tag);
312         if (n > sizeof(a->tag))
313                 n = sizeof(a->tag);
314         memmove(a->tag, tag, n);
315         return a;
316 }
317
318 #define ATTACHER(c) (((struct IPaux*)((c)->aux))->owner)
319
320 static struct chan *ipattach(char *spec)
321 {
322         struct chan *c;
323         int dev;
324
325         dev = atoi(spec);
326         if (dev >= Nfs)
327                 error("bad specification");
328
329         ipgetfs(dev);
330         c = devattach('I', spec);
331         mkqid(&c->qid, QID(0, 0, Qtopdir), 0, QTDIR);
332         c->dev = dev;
333
334         c->aux = newipaux(commonuser(), "none");
335
336         return c;
337 }
338
339 static struct walkqid *ipwalk(struct chan *c, struct chan *nc, char **name,
340                                                           int nname)
341 {
342         struct IPaux *a = c->aux;
343         struct walkqid *w;
344
345         w = devwalk(c, nc, name, nname, NULL, 0, ipgen);
346         if (w != NULL && w->clone != NULL)
347                 w->clone->aux = newipaux(a->owner, a->tag);
348         return w;
349 }
350
351 static int ipstat(struct chan *c, uint8_t * db, int n)
352 {
353         return devstat(c, db, n, NULL, 0, ipgen);
354 }
355
356 static int should_wake(void *arg)
357 {
358         struct conv *cv = arg;
359         /* signal that the conv is closed */
360         if (qisclosed(cv->rq))
361                 return TRUE;
362         return cv->incall != NULL;
363 }
364
365 static struct chan *ipopen(struct chan *c, int omode)
366 {
367         ERRSTACK(2);
368         struct conv *cv, *nc;
369         struct Proto *p;
370         int perm;
371         struct Fs *f;
372
373         /* perm is a lone rwx, not the rwx------ from the conversion */
374         perm = omode_to_rwx(omode) >> 6;
375
376         f = ipfs[c->dev];
377
378         switch (TYPE(c->qid)) {
379                 default:
380                         break;
381                 case Qndb:
382                         if (omode & (O_WRITE | O_TRUNC) && !iseve())
383                                 error(Eperm);
384                         if ((omode & (O_WRITE | O_TRUNC)) == (O_WRITE | O_TRUNC))
385                                 f->ndb[0] = 0;
386                         break;
387                 case Qlog:
388                         netlogopen(f);
389                         break;
390                 case Qiprouter:
391                         iprouteropen(f);
392                         break;
393                 case Qiproute:
394                         break;
395                 case Qtopdir:
396                 case Qprotodir:
397                 case Qconvdir:
398                 case Qstatus:
399                 case Qremote:
400                 case Qlocal:
401                 case Qstats:
402                 case Qbootp:
403                 case Qipselftab:
404                         if (omode & O_WRITE)
405                                 error(Eperm);
406                         break;
407                 case Qsnoop:
408                         if (omode & O_WRITE)
409                                 error(Eperm);
410                         p = f->p[PROTO(c->qid)];
411                         cv = p->conv[CONV(c->qid)];
412                         if (strcmp(ATTACHER(c), cv->owner) != 0 && !iseve())
413                                 error(Eperm);
414                         atomic_inc(&cv->snoopers);
415                         break;
416                 case Qclone:
417                         p = f->p[PROTO(c->qid)];
418                         qlock(&p->qlock);
419                         if (waserror()) {
420                                 qunlock(&p->qlock);
421                                 nexterror();
422                         }
423                         cv = Fsprotoclone(p, ATTACHER(c));
424                         qunlock(&p->qlock);
425                         poperror();
426                         if (cv == NULL) {
427                                 error(Enodev);
428                                 break;
429                         }
430                         /* we only honor nonblock on a clone */
431                         if (c->flag & O_NONBLOCK)
432                                 Fsconvnonblock(cv, TRUE);
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                                 /* we can peek at incall without grabbing the cv qlock.  if
496                                  * anything is there, it'll remain there until we dequeue it.
497                                  * no one else can, since we hold the listenq lock */
498                                 if (cv->nonblock && !cv->incall) {
499                                         set_errno(EAGAIN);
500                                         error("listen queue empty");
501                                 }
502                                 /* wait for a connect */
503                                 rendez_sleep(&cv->listenr, should_wake, cv);
504
505                                 /* if there is a concurrent hangup, they will hold the qlock
506                                  * until the hangup is complete, including closing the cv->rq */
507                                 qlock(&cv->qlock);
508                                 nc = cv->incall;
509                                 if (nc != NULL) {
510                                         cv->incall = nc->next;
511                                         mkqid(&c->qid, QID(PROTO(c->qid), nc->x, Qctl), 0, QTFILE);
512                                         kstrdup(&cv->owner, ATTACHER(c));
513                                         /* O_NONBLOCK/CNONBLOCK when opening listen means the *new*
514                                          * conv is already non-blocking, like accept4() in Linux */
515                                         if (c->flag & O_NONBLOCK)
516                                                 Fsconvnonblock(nc, TRUE);
517                                 }
518                                 qunlock(&cv->qlock);
519
520                                 qunlock(&cv->listenq);
521                                 poperror();
522                         }
523                         closeconv(cv);
524                         poperror();
525                         break;
526         }
527         c->mode = openmode(omode);
528         c->flag |= COPEN;
529         c->offset = 0;
530         return c;
531 }
532
533 static int ipwstat(struct chan *c, uint8_t * dp, int n)
534 {
535         ERRSTACK(2);
536         struct dir *d;
537         struct conv *cv;
538         struct Fs *f;
539         struct Proto *p;
540
541         f = ipfs[c->dev];
542         switch (TYPE(c->qid)) {
543                 default:
544                         error(Eperm);
545                         break;
546                 case Qctl:
547                 case Qdata:
548                         break;
549         }
550
551         d = kzmalloc(sizeof(*d) + n, 0);
552         if (waserror()) {
553                 kfree(d);
554                 nexterror();
555         }
556         n = convM2D(dp, n, d, (char *)&d[1]);
557         if (n == 0)
558                 error(Eshortstat);
559         p = f->p[PROTO(c->qid)];
560         cv = p->conv[CONV(c->qid)];
561         if (!iseve() && strcmp(ATTACHER(c), cv->owner) != 0)
562                 error(Eperm);
563         if (!emptystr(d->uid))
564                 kstrdup(&cv->owner, d->uid);
565         if (d->mode != ~0UL)
566                 cv->perm = d->mode & 0777;
567         poperror();
568         kfree(d);
569         return n;
570 }
571
572 /* Should be able to handle any file type chan. Feel free to extend it. */
573 static char *ipchaninfo(struct chan *ch, char *ret, size_t ret_l)
574 {
575         struct conv *conv;
576         struct Proto *proto;
577         char *p;
578         struct Fs *f;
579
580         f = ipfs[ch->dev];
581
582         switch (TYPE(ch->qid)) {
583                 default:
584                         ret = "Unknown type";
585                         break;
586                 case Qdata:
587                         proto = f->p[PROTO(ch->qid)];
588                         conv = proto->conv[CONV(ch->qid)];
589                         snprintf(ret, ret_l, "Qdata, proto %s, conv idx %d", proto->name,
590                                          conv->x);
591                         break;
592                 case Qarp:
593                         ret = "Qarp";
594                         break;
595                 case Qiproute:
596                         ret = "Qiproute";
597                         break;
598                 case Qlog:
599                         ret = "Qlog";
600                         break;
601                 case Qndb:
602                         ret = "Qndb";
603                         break;
604                 case Qctl:
605                         proto = f->p[PROTO(ch->qid)];
606                         conv = proto->conv[CONV(ch->qid)];
607                         snprintf(ret, ret_l, "Qctl, proto %s, conv idx %d", proto->name,
608                                          conv->x);
609                         break;
610         }
611         return ret;
612 }
613
614 static void closeconv(struct conv *cv)
615 {
616         struct conv *nc;
617         struct Ipmulti *mp;
618
619         qlock(&cv->qlock);
620
621         if (--cv->inuse > 0) {
622                 qunlock(&cv->qlock);
623                 return;
624         }
625
626         /* close all incoming calls since no listen will ever happen */
627         for (nc = cv->incall; nc; nc = cv->incall) {
628                 cv->incall = nc->next;
629                 closeconv(nc);
630         }
631         cv->incall = NULL;
632
633         kstrdup(&cv->owner, network);
634         cv->perm = 0660;
635
636         while ((mp = cv->multi) != NULL)
637                 ipifcremmulti(cv, mp->ma, mp->ia);
638
639         cv->r = NULL;
640         cv->rgen = 0;
641         cv->p->close(cv);
642         cv->state = Idle;
643         qunlock(&cv->qlock);
644 }
645
646 static void ipclose(struct chan *c)
647 {
648         struct Fs *f;
649
650         f = ipfs[c->dev];
651         switch (TYPE(c->qid)) {
652                 default:
653                         break;
654                 case Qlog:
655                         if (c->flag & COPEN)
656                                 netlogclose(f);
657                         break;
658                 case Qiprouter:
659                         if (c->flag & COPEN)
660                                 iprouterclose(f);
661                         break;
662                 case Qdata:
663                 case Qctl:
664                 case Qerr:
665                         if (c->flag & COPEN)
666                                 closeconv(f->p[PROTO(c->qid)]->conv[CONV(c->qid)]);
667                         break;
668                 case Qsnoop:
669                         if (c->flag & COPEN)
670                                 atomic_dec(&f->p[PROTO(c->qid)]->conv[CONV(c->qid)]->snoopers);
671                         break;
672         }
673         kfree(((struct IPaux *)c->aux)->owner);
674         kfree(c->aux);
675 }
676
677 enum {
678         Statelen = 32 * 1024,
679 };
680
681 static long ipread(struct chan *ch, void *a, long n, int64_t off)
682 {
683         struct conv *c;
684         struct Proto *x;
685         char *buf, *p;
686         long rv;
687         struct Fs *f;
688         uint32_t offset = off;
689         size_t sofar;
690
691         f = ipfs[ch->dev];
692
693         p = a;
694         switch (TYPE(ch->qid)) {
695                 default:
696                         error(Eperm);
697                 case Qtopdir:
698                 case Qprotodir:
699                 case Qconvdir:
700                         return devdirread(ch, a, n, 0, 0, ipgen);
701                 case Qarp:
702                         return arpread(f->arp, a, offset, n);
703                 case Qbootp:
704                         return bootpread(a, offset, n);
705                 case Qndb:
706                         return readstr(offset, a, n, f->ndb);
707                 case Qiproute:
708                         return routeread(f, a, offset, n);
709                 case Qiprouter:
710                         return iprouterread(f, a, n);
711                 case Qipselftab:
712                         return ipselftabread(f, a, offset, n);
713                 case Qlog:
714                         return netlogread(f, a, offset, n);
715                 case Qctl:
716                         snprintf(get_cur_genbuf(), GENBUF_SZ, "%lu", CONV(ch->qid));
717                         return readstr(offset, p, n, get_cur_genbuf());
718                 case Qremote:
719                         buf = kzmalloc(Statelen, 0);
720                         x = f->p[PROTO(ch->qid)];
721                         c = x->conv[CONV(ch->qid)];
722                         if (x->remote == NULL) {
723                                 snprintf(buf, Statelen, "%I!%d\n", c->raddr, c->rport);
724                         } else {
725                                 (*x->remote) (c, buf, Statelen - 2);
726                         }
727                         rv = readstr(offset, p, n, buf);
728                         kfree(buf);
729                         return rv;
730                 case Qlocal:
731                         buf = kzmalloc(Statelen, 0);
732                         x = f->p[PROTO(ch->qid)];
733                         c = x->conv[CONV(ch->qid)];
734                         if (x->local == NULL) {
735                                 snprintf(buf, Statelen, "%I!%d\n", c->laddr, c->lport);
736                         } else {
737                                 (*x->local) (c, buf, Statelen - 2);
738                         }
739                         rv = readstr(offset, p, n, buf);
740                         kfree(buf);
741                         return rv;
742                 case Qstatus:
743                         /* this all is a bit screwed up since the size of some state's
744                          * buffers will change from one invocation to another.  a reader
745                          * will come in and read the entire buffer.  then it will come again
746                          * and read from the next offset, expecting EOF.  if the buffer
747                          * changed sizes, it'll reprint the end of the buffer slightly. */
748                         buf = kzmalloc(Statelen, 0);
749                         x = f->p[PROTO(ch->qid)];
750                         c = x->conv[CONV(ch->qid)];
751                         sofar = (*x->state) (c, buf, Statelen - 2);
752                         sofar += snprintf(buf + sofar, Statelen - 2 - sofar, "nonblock %s\n",
753                                           c->nonblock ? "on" : "off");
754                         rv = readstr(offset, p, n, buf);
755                         kfree(buf);
756                         return rv;
757                 case Qdata:
758                         c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
759                         return qread(c->rq, a, n);
760                 case Qerr:
761                         c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
762                         return qread(c->eq, a, n);
763                 case Qsnoop:
764                         c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
765                         return qread(c->sq, a, n);
766                 case Qstats:
767                         x = f->p[PROTO(ch->qid)];
768                         if (x->stats == NULL)
769                                 error("stats not implemented");
770                         buf = kzmalloc(Statelen, 0);
771                         (*x->stats) (x, buf, Statelen);
772                         rv = readstr(offset, p, n, buf);
773                         kfree(buf);
774                         return rv;
775         }
776 }
777
778 static struct block *ipbread(struct chan *ch, long n, uint32_t offset)
779 {
780         struct conv *c;
781         struct Proto *x;
782         struct Fs *f;
783
784         switch (TYPE(ch->qid)) {
785                 case Qdata:
786                         f = ipfs[ch->dev];
787                         x = f->p[PROTO(ch->qid)];
788                         c = x->conv[CONV(ch->qid)];
789                         return qbread(c->rq, n);
790                 default:
791                         return devbread(ch, n, offset);
792         }
793 }
794
795 /*
796  *  set local address to be that of the ifc closest to remote address
797  */
798 static void setladdr(struct conv *c)
799 {
800         findlocalip(c->p->f, c->laddr, c->raddr);
801 }
802
803 /*
804  *  set a local port making sure the quad of raddr,rport,laddr,lport is unique
805  */
806 static char *setluniqueport(struct conv *c, int lport)
807 {
808         struct Proto *p;
809         struct conv *xp;
810         int x;
811
812         p = c->p;
813
814         qlock(&p->qlock);
815         for (x = 0; x < p->nc; x++) {
816                 xp = p->conv[x];
817                 if (xp == NULL)
818                         break;
819                 if (xp == c)
820                         continue;
821                 if ((xp->state == Connected || xp->state == Announced)
822                         && xp->lport == lport
823                         && xp->rport == c->rport
824                         && ipcmp(xp->raddr, c->raddr) == 0
825                         && ipcmp(xp->laddr, c->laddr) == 0) {
826                         qunlock(&p->qlock);
827                         return "address in use";
828                 }
829         }
830         c->lport = lport;
831         qunlock(&p->qlock);
832         return NULL;
833 }
834
835 /*
836  *  pick a local port and set it
837  */
838 static void setlport(struct conv *c)
839 {
840         struct Proto *p;
841         uint16_t *pp;
842         int x, found;
843
844         p = c->p;
845         if (c->restricted)
846                 pp = &p->nextrport;
847         else
848                 pp = &p->nextport;
849         qlock(&p->qlock);
850         for (;; (*pp)++) {
851                 /*
852                  * Fsproto initialises p->nextport to 0 and the restricted
853                  * ports (p->nextrport) to 600.
854                  * Restricted ports must lie between 600 and 1024.
855                  * For the initial condition or if the unrestricted port number
856                  * has wrapped round, select a random port between 5000 and 1<<15
857                  * to start at.
858                  */
859                 if (c->restricted) {
860                         if (*pp >= 1024)
861                                 *pp = 600;
862                 } else
863                         while (*pp < 5000)
864                                 *pp = nrand(1 << 15);
865
866                 found = 0;
867                 for (x = 0; x < p->nc; x++) {
868                         if (p->conv[x] == NULL)
869                                 break;
870                         if (p->conv[x]->lport == *pp) {
871                                 found = 1;
872                                 break;
873                         }
874                 }
875                 if (!found)
876                         break;
877         }
878         c->lport = (*pp)++;
879         qunlock(&p->qlock);
880 }
881
882 /*
883  *  set a local address and port from a string of the form
884  *      [address!]port[!r]
885  */
886 static char *setladdrport(struct conv *c, char *str, int announcing)
887 {
888         char *p;
889         char *rv;
890         uint16_t lport;
891         uint8_t addr[IPaddrlen];
892
893         rv = NULL;
894
895         /*
896          *  ignore restricted part if it exists.  it's
897          *  meaningless on local ports.
898          */
899         p = strchr(str, '!');
900         if (p != NULL) {
901                 *p++ = 0;
902                 if (strcmp(p, "r") == 0)
903                         p = NULL;
904         }
905
906         c->lport = 0;
907         if (p == NULL) {
908                 if (announcing)
909                         ipmove(c->laddr, IPnoaddr);
910                 else
911                         setladdr(c);
912                 p = str;
913         } else {
914                 if (strcmp(str, "*") == 0)
915                         ipmove(c->laddr, IPnoaddr);
916                 else {
917                         parseip(addr, str);
918                         if (ipforme(c->p->f, addr))
919                                 ipmove(c->laddr, addr);
920                         else
921                                 return "not a local IP address";
922                 }
923         }
924
925         /* one process can get all connections */
926         if (announcing && strcmp(p, "*") == 0) {
927                 if (!iseve())
928                         error(Eperm);
929                 return setluniqueport(c, 0);
930         }
931
932         lport = atoi(p);
933         if (lport <= 0)
934                 setlport(c);
935         else
936                 rv = setluniqueport(c, lport);
937         return rv;
938 }
939
940 static char *setraddrport(struct conv *c, char *str)
941 {
942         char *p;
943
944         p = strchr(str, '!');
945         if (p == NULL)
946                 return "malformed address";
947         *p++ = 0;
948         parseip(c->raddr, str);
949         c->rport = atoi(p);
950         p = strchr(p, '!');
951         if (p) {
952                 if (strstr(p, "!r") != NULL)
953                         c->restricted = 1;
954         }
955         return NULL;
956 }
957
958 /*
959  *  called by protocol connect routine to set addresses
960  */
961 char *Fsstdconnect(struct conv *c, char *argv[], int argc)
962 {
963         char *p;
964
965         switch (argc) {
966                 default:
967                         return "bad args to connect";
968                 case 2:
969                         p = setraddrport(c, argv[1]);
970                         if (p != NULL)
971                                 return p;
972                         setladdr(c);
973                         setlport(c);
974                         break;
975                 case 3:
976                         p = setraddrport(c, argv[1]);
977                         if (p != NULL)
978                                 return p;
979                         p = setladdrport(c, argv[2], 0);
980                         if (p != NULL)
981                                 return p;
982         }
983
984         if ((memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
985                  memcmp(c->laddr, v4prefix, IPv4off) == 0)
986                 || ipcmp(c->raddr, IPnoaddr) == 0)
987                 c->ipversion = V4;
988         else
989                 c->ipversion = V6;
990
991         return NULL;
992 }
993
994 /*
995  *  initiate connection and sleep till its set up
996  */
997 static int connected(void *a)
998 {
999         return ((struct conv *)a)->state == Connected;
1000 }
1001
1002 static void connectctlmsg(struct Proto *x, struct conv *c, struct cmdbuf *cb)
1003 {
1004         ERRSTACK(1);
1005         char *p;
1006
1007         if (c->state != 0)
1008                 error(Econinuse);
1009         c->state = Connecting;
1010         c->cerr[0] = '\0';
1011         if (x->connect == NULL)
1012                 error("connect not supported");
1013         p = x->connect(c, cb->f, cb->nf);
1014         if (p != NULL)
1015                 error(p);
1016
1017         qunlock(&c->qlock);
1018         if (waserror()) {
1019                 qlock(&c->qlock);
1020                 nexterror();
1021         }
1022         rendez_sleep(&c->cr, connected, c);
1023         qlock(&c->qlock);
1024         poperror();
1025
1026         if (c->cerr[0] != '\0')
1027                 error(c->cerr);
1028 }
1029
1030 /*
1031  *  called by protocol announce routine to set addresses
1032  */
1033 char *Fsstdannounce(struct conv *c, char *argv[], int argc)
1034 {
1035         memset(c->raddr, 0, sizeof(c->raddr));
1036         c->rport = 0;
1037         switch (argc) {
1038                 default:
1039                         return "bad args to announce";
1040                 case 2:
1041                         return setladdrport(c, argv[1], 1);
1042         }
1043 }
1044
1045 /*
1046  *  initiate announcement and sleep till its set up
1047  */
1048 static int announced(void *a)
1049 {
1050         return ((struct conv *)a)->state == Announced;
1051 }
1052
1053 static void announcectlmsg(struct Proto *x, struct conv *c, struct cmdbuf *cb)
1054 {
1055         ERRSTACK(1);
1056         char *p;
1057
1058         if (c->state != 0)
1059                 error(Econinuse);
1060         c->state = Announcing;
1061         c->cerr[0] = '\0';
1062         if (x->announce == NULL)
1063                 error("announce not supported");
1064         p = x->announce(c, cb->f, cb->nf);
1065         if (p != NULL)
1066                 error(p);
1067
1068         qunlock(&c->qlock);
1069         if (waserror()) {
1070                 qlock(&c->qlock);
1071                 nexterror();
1072         }
1073         rendez_sleep(&c->cr, announced, c);
1074         qlock(&c->qlock);
1075         poperror();
1076
1077         if (c->cerr[0] != '\0')
1078                 error(c->cerr);
1079 }
1080
1081 /*
1082  *  called by protocol bind routine to set addresses
1083  */
1084 char *Fsstdbind(struct conv *c, char *argv[], int argc)
1085 {
1086         switch (argc) {
1087                 default:
1088                         return "bad args to bind";
1089                 case 2:
1090                         return setladdrport(c, argv[1], 0);
1091         }
1092 }
1093
1094 void Fsconvnonblock(struct conv *cv, bool onoff)
1095 {
1096         qnonblock(cv->wq, onoff);
1097         qnonblock(cv->rq, onoff);
1098         cv->nonblock = onoff;
1099 }
1100
1101 static void bindctlmsg(struct Proto *x, struct conv *c, struct cmdbuf *cb)
1102 {
1103         char *p;
1104
1105         if (x->bind == NULL)
1106                 p = Fsstdbind(c, cb->f, cb->nf);
1107         else
1108                 p = x->bind(c, cb->f, cb->nf);
1109         if (p != NULL)
1110                 error(p);
1111 }
1112
1113 static void nonblockctlmsg(struct conv *c, struct cmdbuf *cb)
1114 {
1115         if (cb->nf < 2)
1116                 goto err;
1117         if (!strcmp(cb->f[1], "on"))
1118                 Fsconvnonblock(c, TRUE);
1119         else if (!strcmp(cb->f[1], "off"))
1120                 Fsconvnonblock(c, FALSE);
1121         else
1122                 goto err;
1123         return;
1124 err:
1125         set_errno(EINVAL);
1126         error("nonblock [on|off]");
1127 }
1128
1129 static void tosctlmsg(struct conv *c, struct cmdbuf *cb)
1130 {
1131         if (cb->nf < 2)
1132                 c->tos = 0;
1133         else
1134                 c->tos = atoi(cb->f[1]);
1135 }
1136
1137 static void ttlctlmsg(struct conv *c, struct cmdbuf *cb)
1138 {
1139         if (cb->nf < 2)
1140                 c->ttl = MAXTTL;
1141         else
1142                 c->ttl = atoi(cb->f[1]);
1143 }
1144
1145 static long ipwrite(struct chan *ch, void *v, long n, int64_t off)
1146 {
1147         ERRSTACK(1);
1148         struct conv *c;
1149         struct Proto *x;
1150         char *p;
1151         struct cmdbuf *cb;
1152         uint8_t ia[IPaddrlen], ma[IPaddrlen];
1153         struct Fs *f;
1154         char *a;
1155
1156         a = v;
1157         f = ipfs[ch->dev];
1158
1159         switch (TYPE(ch->qid)) {
1160                 default:
1161                         error(Eperm);
1162                 case Qdata:
1163                         x = f->p[PROTO(ch->qid)];
1164                         c = x->conv[CONV(ch->qid)];
1165                         qwrite(c->wq, a, n);
1166                         break;
1167                 case Qarp:
1168                         return arpwrite(f, a, n);
1169                 case Qiproute:
1170                         return routewrite(f, ch, a, n);
1171                 case Qlog:
1172                         netlogctl(f, a, n);
1173                         return n;
1174                 case Qndb:
1175                         return ndbwrite(f, a, off, n);
1176                 case Qctl:
1177                         x = f->p[PROTO(ch->qid)];
1178                         c = x->conv[CONV(ch->qid)];
1179                         cb = parsecmd(a, n);
1180
1181                         qlock(&c->qlock);
1182                         if (waserror()) {
1183                                 qunlock(&c->qlock);
1184                                 kfree(cb);
1185                                 nexterror();
1186                         }
1187                         if (cb->nf < 1)
1188                                 error("short control request");
1189                         if (strcmp(cb->f[0], "connect") == 0)
1190                                 connectctlmsg(x, c, cb);
1191                         else if (strcmp(cb->f[0], "announce") == 0)
1192                                 announcectlmsg(x, c, cb);
1193                         else if (strcmp(cb->f[0], "bind") == 0)
1194                                 bindctlmsg(x, c, cb);
1195                         else if (strcmp(cb->f[0], "nonblock") == 0)
1196                                 nonblockctlmsg(c, cb);
1197                         else if (strcmp(cb->f[0], "ttl") == 0)
1198                                 ttlctlmsg(c, cb);
1199                         else if (strcmp(cb->f[0], "tos") == 0)
1200                                 tosctlmsg(c, cb);
1201                         else if (strcmp(cb->f[0], "ignoreadvice") == 0)
1202                                 c->ignoreadvice = 1;
1203                         else if (strcmp(cb->f[0], "addmulti") == 0) {
1204                                 if (cb->nf < 2)
1205                                         error("addmulti needs interface address");
1206                                 if (cb->nf == 2) {
1207                                         if (!ipismulticast(c->raddr))
1208                                                 error("addmulti for a non multicast address");
1209                                         parseip(ia, cb->f[1]);
1210                                         ipifcaddmulti(c, c->raddr, ia);
1211                                 } else {
1212                                         parseip(ma, cb->f[2]);
1213                                         if (!ipismulticast(ma))
1214                                                 error("addmulti for a non multicast address");
1215                                         parseip(ia, cb->f[1]);
1216                                         ipifcaddmulti(c, ma, ia);
1217                                 }
1218                         } else if (strcmp(cb->f[0], "remmulti") == 0) {
1219                                 if (cb->nf < 2)
1220                                         error("remmulti needs interface address");
1221                                 if (!ipismulticast(c->raddr))
1222                                         error("remmulti for a non multicast address");
1223                                 parseip(ia, cb->f[1]);
1224                                 ipifcremmulti(c, c->raddr, ia);
1225                         } else if (x->ctl != NULL) {
1226                                 p = x->ctl(c, cb->f, cb->nf);
1227                                 if (p != NULL)
1228                                         error(p);
1229                         } else
1230                                 error("unknown control request");
1231                         qunlock(&c->qlock);
1232                         kfree(cb);
1233                         poperror();
1234         }
1235         return n;
1236 }
1237
1238 static long ipbwrite(struct chan *ch, struct block *bp, uint32_t offset)
1239 {
1240         struct conv *c;
1241         struct Proto *x;
1242         struct Fs *f;
1243         int n;
1244
1245         switch (TYPE(ch->qid)) {
1246                 case Qdata:
1247                         f = ipfs[ch->dev];
1248                         x = f->p[PROTO(ch->qid)];
1249                         c = x->conv[CONV(ch->qid)];
1250                         if (bp->next)
1251                                 bp = concatblock(bp);
1252                         n = BLEN(bp);
1253                         qbwrite(c->wq, bp);
1254                         return n;
1255                 default:
1256                         return devbwrite(ch, bp, offset);
1257         }
1258 }
1259
1260 static void ip_wake_cb(struct queue *q, void *data, int filter)
1261 {
1262         struct conv *conv = (struct conv*)data;
1263         struct fd_tap *tap_i;
1264         /* For these two, we want to ignore events on the opposite end of the
1265          * queues.  For instance, we want to know when the WQ is writable.  Our
1266          * writes will actually make it readable - we don't want to trigger a tap
1267          * for that.  However, qio doesn't know how/why we are using a queue, or
1268          * even who the ends are (hence the callbacks) */
1269         if ((filter & FDTAP_FILT_READABLE) && (q == conv->wq))
1270                 return;
1271         if ((filter & FDTAP_FILT_WRITABLE) && (q == conv->rq))
1272                 return;
1273         /* At this point, we have an event we want to send to our taps (if any).
1274          * The lock protects list integrity and the existence of the tap.
1275          *
1276          * Previously, I thought of using the conv qlock.  That actually breaks, due
1277          * to weird usages of the qlock (someone holds it for a long time, blocking
1278          * the inbound wakeup from etherread4).
1279          *
1280          * I opted for a spinlock for a couple reasons:
1281          * - fire_tap should not block.  ideally it'll be fast too (it's mostly a
1282          * send_event).
1283          * - our callers might not want to block.  A lot of network wakeups will
1284          * come network processes (etherread4) or otherwise unrelated to this
1285          * particular conversation.  I'd rather do something like fire off a KMSG
1286          * than block those.
1287          * - if fire_tap takes a while, holding the lock only slows down other
1288          * events on this *same* conversation, or other tap registration.  not a
1289          * huge deal. */
1290         spin_lock(&conv->tap_lock);
1291         SLIST_FOREACH(tap_i, &conv->data_taps, link)
1292                 fire_tap(tap_i, filter);
1293         spin_unlock(&conv->tap_lock);
1294 }
1295
1296 int iptapfd(struct chan *chan, struct fd_tap *tap, int cmd)
1297 {
1298         struct conv *conv;
1299         struct Proto *x;
1300         struct Fs *f;
1301         int ret;
1302
1303         #define DEVIP_LEGAL_DATA_TAPS (FDTAP_FILT_READABLE | FDTAP_FILT_WRITABLE | \
1304                                        FDTAP_FILT_HANGUP)
1305
1306         /* That's a lot of pointers to get to the conv! */
1307         f = ipfs[chan->dev];
1308         x = f->p[PROTO(chan->qid)];
1309         conv = x->conv[CONV(chan->qid)];
1310
1311         switch (TYPE(chan->qid)) {
1312                 case Qdata:
1313                         if (tap->filter & ~DEVIP_LEGAL_DATA_TAPS) {
1314                                 set_errno(ENOSYS);
1315                                 set_errstr("Unsupported #I data tap, must be %p",
1316                                            DEVIP_LEGAL_DATA_TAPS);
1317                                 return -1;
1318                         }
1319                         spin_lock(&conv->tap_lock);
1320                         switch (cmd) {
1321                                 case (FDTAP_CMD_ADD):
1322                                         if (SLIST_EMPTY(&conv->data_taps)) {
1323                                                 qio_set_wake_cb(conv->rq, ip_wake_cb, conv);
1324                                                 qio_set_wake_cb(conv->wq, ip_wake_cb, conv);
1325                                         }
1326                                         SLIST_INSERT_HEAD(&conv->data_taps, tap, link);
1327                                         ret = 0;
1328                                         break;
1329                                 case (FDTAP_CMD_REM):
1330                                         SLIST_REMOVE(&conv->data_taps, tap, fd_tap, link);
1331                                         if (SLIST_EMPTY(&conv->data_taps)) {
1332                                                 qio_set_wake_cb(conv->rq, 0, conv);
1333                                                 qio_set_wake_cb(conv->wq, 0, conv);
1334                                         }
1335                                         ret = 0;
1336                                         break;
1337                                 default:
1338                                         set_errno(ENOSYS);
1339                                         set_errstr("Unsupported #I data tap command");
1340                                         ret = -1;
1341                         }
1342                         spin_unlock(&conv->tap_lock);
1343                         return ret;
1344                 default:
1345                         set_errno(ENOSYS);
1346                         set_errstr("Can't tap #I file type %d", TYPE(chan->qid));
1347                         return -1;
1348         }
1349 }
1350
1351 struct dev ipdevtab __devtab = {
1352         .dc = 'I',
1353         .name = "ip",
1354
1355         .reset = ipreset,
1356         .init = ipinit,
1357         .shutdown = devshutdown,
1358         .attach = ipattach,
1359         .walk = ipwalk,
1360         .stat = ipstat,
1361         .open = ipopen,
1362         .create = devcreate,
1363         .close = ipclose,
1364         .read = ipread,
1365         .bread = ipbread,
1366         .write = ipwrite,
1367         .bwrite = ipbwrite,
1368         .remove = devremove,
1369         .wstat = ipwstat,
1370         .power = devpower,
1371         .chaninfo = ipchaninfo,
1372         .tapfd = iptapfd,
1373 };
1374
1375 int Fsproto(struct Fs *f, struct Proto *p)
1376 {
1377         if (f->np >= Maxproto)
1378                 return -1;
1379
1380         qlock_init(&p->qlock);
1381         p->f = f;
1382
1383         if (p->ipproto > 0) {
1384                 if (f->t2p[p->ipproto] != NULL)
1385                         return -1;
1386                 f->t2p[p->ipproto] = p;
1387         }
1388
1389         p->qid.type = QTDIR;
1390         p->qid.path = QID(f->np, 0, Qprotodir);
1391         p->conv = kzmalloc(sizeof(struct conv *) * (p->nc + 1), 0);
1392         if (p->conv == NULL)
1393                 panic("Fsproto");
1394
1395         p->x = f->np;
1396         p->nextport = 0;
1397         p->nextrport = 600;
1398         f->p[f->np++] = p;
1399
1400         return 0;
1401 }
1402
1403 /*
1404  *  return true if this protocol is
1405  *  built in
1406  */
1407 int Fsbuiltinproto(struct Fs *f, uint8_t proto)
1408 {
1409         return f->t2p[proto] != NULL;
1410 }
1411
1412 /*
1413  *  called with protocol locked
1414  */
1415 struct conv *Fsprotoclone(struct Proto *p, char *user)
1416 {
1417         struct conv *c, **pp, **ep;
1418
1419 retry:
1420         c = NULL;
1421         ep = &p->conv[p->nc];
1422         for (pp = p->conv; pp < ep; pp++) {
1423                 c = *pp;
1424                 if (c == NULL) {
1425                         c = kzmalloc(sizeof(struct conv), 0);
1426                         if (c == NULL)
1427                                 error(Enomem);
1428                         qlock_init(&c->qlock);
1429                         qlock_init(&c->listenq);
1430                         rendez_init(&c->cr);
1431                         rendez_init(&c->listenr);
1432                         SLIST_INIT(&c->data_taps);      /* already = 0; set to be futureproof */
1433                         spinlock_init(&c->tap_lock);
1434                         qlock(&c->qlock);
1435                         c->p = p;
1436                         c->x = pp - p->conv;
1437                         if (p->ptclsize != 0) {
1438                                 c->ptcl = kzmalloc(p->ptclsize, 0);
1439                                 if (c->ptcl == NULL) {
1440                                         kfree(c);
1441                                         error(Enomem);
1442                                 }
1443                         }
1444                         *pp = c;
1445                         p->ac++;
1446                         c->eq = qopen(1024, Qmsg, 0, 0);
1447                         (*p->create) (c);
1448                         assert(c->rq && c->wq);
1449                         break;
1450                 }
1451                 if (canqlock(&c->qlock)) {
1452                         /*
1453                          *  make sure both processes and protocol
1454                          *  are done with this Conv
1455                          */
1456                         if (c->inuse == 0 && (p->inuse == NULL || (*p->inuse) (c) == 0))
1457                                 break;
1458
1459                         qunlock(&c->qlock);
1460                 }
1461         }
1462         if (pp >= ep) {
1463                 if (p->gc != NULL && (*p->gc) (p))
1464                         goto retry;
1465                 return NULL;
1466         }
1467
1468         c->inuse = 1;
1469         kstrdup(&c->owner, user);
1470         c->perm = 0660;
1471         c->state = Idle;
1472         ipmove(c->laddr, IPnoaddr);
1473         ipmove(c->raddr, IPnoaddr);
1474         c->r = NULL;
1475         c->rgen = 0;
1476         c->lport = 0;
1477         c->rport = 0;
1478         c->restricted = 0;
1479         c->ttl = MAXTTL;
1480         c->tos = DFLTTOS;
1481         c->nonblock = FALSE;
1482         qreopen(c->rq);
1483         qreopen(c->wq);
1484         qreopen(c->eq);
1485
1486         qunlock(&c->qlock);
1487         return c;
1488 }
1489
1490 int Fsconnected(struct conv *c, char *msg)
1491 {
1492         if (msg != NULL && *msg != '\0')
1493                 strncpy(c->cerr, msg, sizeof(c->cerr));
1494
1495         switch (c->state) {
1496
1497                 case Announcing:
1498                         c->state = Announced;
1499                         break;
1500
1501                 case Connecting:
1502                         c->state = Connected;
1503                         break;
1504         }
1505
1506         rendez_wakeup(&c->cr);
1507         return 0;
1508 }
1509
1510 struct Proto *Fsrcvpcol(struct Fs *f, uint8_t proto)
1511 {
1512         if (f->ipmux)
1513                 return f->ipmux;
1514         else
1515                 return f->t2p[proto];
1516 }
1517
1518 struct Proto *Fsrcvpcolx(struct Fs *f, uint8_t proto)
1519 {
1520         return f->t2p[proto];
1521 }
1522
1523 /*
1524  *  called with protocol locked
1525  */
1526 struct conv *Fsnewcall(struct conv *c, uint8_t * raddr, uint16_t rport,
1527                                            uint8_t * laddr, uint16_t lport, uint8_t version)
1528 {
1529         struct conv *nc;
1530         struct conv **l;
1531         int i;
1532
1533         qlock(&c->qlock);
1534         i = 0;
1535         for (l = &c->incall; *l; l = &(*l)->next)
1536                 i++;
1537         if (i >= Maxincall) {
1538                 qunlock(&c->qlock);
1539                 return NULL;
1540         }
1541
1542         /* find a free conversation */
1543         nc = Fsprotoclone(c->p, network);
1544         if (nc == NULL) {
1545                 qunlock(&c->qlock);
1546                 return NULL;
1547         }
1548         ipmove(nc->raddr, raddr);
1549         nc->rport = rport;
1550         ipmove(nc->laddr, laddr);
1551         nc->lport = lport;
1552         nc->next = NULL;
1553         *l = nc;
1554         nc->state = Connected;
1555         nc->ipversion = version;
1556
1557         qunlock(&c->qlock);
1558
1559         rendez_wakeup(&c->listenr);
1560
1561         return nc;
1562 }
1563
1564 static long ndbwrite(struct Fs *f, char *a, uint32_t off, int n)
1565 {
1566         if (off > strlen(f->ndb))
1567                 error(Eio);
1568         if (off + n >= sizeof(f->ndb) - 1)
1569                 error(Eio);
1570         memmove(f->ndb + off, a, n);
1571         f->ndb[off + n] = 0;
1572         f->ndbvers++;
1573         f->ndbmtime = seconds();
1574         return n;
1575 }
1576
1577 uint32_t scalednconv(void)
1578 {
1579         //if(conf.npage*BY2PG >= 128*MB)
1580         return Nchans * 4;
1581         //  return Nchans;
1582 }