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