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