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