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